Provide an option in bench_pictures to count pixel ram.

In SkLruImageCache, provide an option to keep all pixels, and document
the new behavior.

In gm/factory.cpp, set the budget for the Lru image cache to 1, to
retain (basically) the old behavior.

BUG=https://code.google.com/p/skia/issues/detail?id=1010

Review URL: https://codereview.chromium.org/12378075

git-svn-id: http://skia.googlecode.com/svn/trunk@7972 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/factory.cpp b/gm/factory.cpp
index b55532e..f4e8ae3 100644
--- a/gm/factory.cpp
+++ b/gm/factory.cpp
@@ -42,7 +42,7 @@
             SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget);
             // Create a cache which will boot the pixels out anytime the
             // bitmap is unlocked.
-            SkAutoTUnref<SkLruImageCache> cache(SkNEW_ARGS(SkLruImageCache, (0)));
+            SkAutoTUnref<SkLruImageCache> cache(SkNEW_ARGS(SkLruImageCache, (1)));
             factory.setImageCache(cache);
             factory.installPixelRef(data, &fBitmap);
         }
diff --git a/include/lazy/SkLruImageCache.h b/include/lazy/SkLruImageCache.h
index 4444600..05d2815 100644
--- a/include/lazy/SkLruImageCache.h
+++ b/include/lazy/SkLruImageCache.h
@@ -28,7 +28,21 @@
     CacheStatus getCacheStatus(intptr_t ID) const SK_OVERRIDE;
 #endif
 
-    void setBudget(size_t newBudget);
+    /**
+     *  Set the byte limit on cached pixels. If more bytes are used than this, the cache will free
+     *  unpinned memory until under the new limit or until all unpinned memory is freed. This will
+     *  never free pinned memory, so the cache can potentially remain over the limit. The limit is
+     *  enforced each time memory is allocated or released.
+     *  0 is a special flag for an infinite budget.
+     *  @return size_t The previous limit.
+     */
+    size_t setImageCacheLimit(size_t newLimit);
+
+    /**
+     *  Return the number of bytes of memory currently in use by the cache. Can include memory that
+     *  is no longer pinned, but has not been freed.
+     */
+    size_t getImageCacheUsed() const { return fRamUsed; }
 
     virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) SK_OVERRIDE;
     virtual void* pinCache(intptr_t ID) SK_OVERRIDE;
diff --git a/src/lazy/SkLruImageCache.cpp b/src/lazy/SkLruImageCache.cpp
index 62e2953..6beb8a4 100644
--- a/src/lazy/SkLruImageCache.cpp
+++ b/src/lazy/SkLruImageCache.cpp
@@ -87,10 +87,12 @@
 }
 #endif
 
-void SkLruImageCache::setBudget(size_t newBudget) {
+size_t SkLruImageCache::setImageCacheLimit(size_t newLimit) {
+    size_t oldLimit = fRamBudget;
     SkAutoMutexAcquire ac(&fMutex);
-    fRamBudget = newBudget;
+    fRamBudget = newLimit;
     this->purgeIfNeeded();
+    return oldLimit;
 }
 
 void* SkLruImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) {
@@ -168,7 +170,9 @@
 
 void SkLruImageCache::purgeIfNeeded() {
     // Mutex is already locked.
-    this->purgeTilAtOrBelow(fRamBudget);
+    if (fRamBudget > 0) {
+        this->purgeTilAtOrBelow(fRamBudget);
+    }
 }
 
 void SkLruImageCache::purgeTilAtOrBelow(size_t limit) {
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
index 0c7644f..d027db9 100644
--- a/tools/bench_pictures_main.cpp
+++ b/tools/bench_pictures_main.cpp
@@ -26,6 +26,7 @@
 SkBenchLogger gLogger;
 
 // Flags used by this file, in alphabetical order.
+DEFINE_bool(countRAM, false, "Count the RAM used for bitmap pixels in each skp file");
 DECLARE_bool(deferImageDecoding);
 DEFINE_string(filter, "",
         "type:flag : Enable canvas filtering to disable a paint flag, "
@@ -173,6 +174,13 @@
         return false;
     }
 
+    // Since the old picture has been deleted, all pixels should be cleared.
+    SkASSERT(gLruImageCache.getImageCacheUsed() == 0);
+    if (FLAGS_countRAM) {
+        // Set the limit to zero, so all pixels will be kept
+        gLruImageCache.setImageCacheLimit(0);
+    }
+
     bool success = false;
     SkPicture* picture;
     if (FLAGS_deferImageDecoding) {
@@ -204,11 +212,29 @@
         int32_t cacheHits = SkLazyPixelRef::GetCacheHits();
         int32_t cacheMisses = SkLazyPixelRef::GetCacheMisses();
         SkLazyPixelRef::ResetCacheStats();
-        SkDebugf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses));
+        SkString hitString;
+        hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses));
+        gLogger.logProgress(hitString);
         gTotalCacheHits += cacheHits;
         gTotalCacheMisses += cacheMisses;
     }
 #endif
+    if (FLAGS_countRAM) {
+        SkString ramCount("RAM used for bitmaps: ");
+        size_t bytes = gLruImageCache.getImageCacheUsed();
+        if (bytes > 1024) {
+            size_t kb = bytes / 1024;
+            if (kb > 1024) {
+                size_t mb = kb / 1024;
+                ramCount.appendf("%zi MB\n", mb);
+            } else {
+                ramCount.appendf("%zi KB\n", kb);
+            }
+        } else {
+            ramCount.appendf("%zi bytes\n", bytes);
+        }
+        gLogger.logProgress(ramCount);
+    }
 
     return true;
 }