add mipmaps to scaledimagecache

BUG=

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

git-svn-id: http://skia.googlecode.com/svn/trunk@10305 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkScaledImageCache.cpp b/src/core/SkScaledImageCache.cpp
index 8d7b81b..84a5c56 100644
--- a/src/core/SkScaledImageCache.cpp
+++ b/src/core/SkScaledImageCache.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "SkScaledImageCache.h"
+#include "SkMipMap.h"
 #include "SkPixelRef.h"
 #include "SkRect.h"
 
@@ -110,10 +111,21 @@
 struct SkScaledImageCache::Rec {
     Rec(const Key& key, const SkBitmap& bm) : fKey(key), fBitmap(bm) {
         fLockCount = 1;
+        fMip = NULL;
     }
-
+    
+    Rec(const Key& key, const SkMipMap* mip) : fKey(key) {
+        fLockCount = 1;
+        fMip = mip;
+        mip->ref();
+    }
+    
+    ~Rec() {
+        SkSafeUnref(fMip);
+    }
+    
     size_t bytesUsed() const {
-        return fBitmap.getSize();
+        return fMip ? fMip->getSize() : fBitmap.getSize();
     }
 
     Rec*    fNext;
@@ -123,7 +135,10 @@
     Key     fKey;
 
     int32_t fLockCount;
+    
+    // we use either fBitmap or fMip, but not both
     SkBitmap fBitmap;
+    const SkMipMap* fMip;
 };
 
 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
@@ -143,44 +158,89 @@
     }
 }
 
-SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig,
+SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkBitmap& orig,
                                                         SkScalar scaleX,
-                                                        SkScalar scaleY,
-                                                        SkBitmap* scaled) {
+                                                        SkScalar scaleY) {
     Key key;
     if (!key.init(orig, scaleX, scaleY)) {
         return NULL;
     }
-
+    
     Rec* rec = fHead;
     while (rec != NULL) {
         if (rec->fKey == key) {
             this->moveToHead(rec);  // for our LRU
             rec->fLockCount += 1;
-            *scaled = rec->fBitmap;
-//            SkDebugf("Found: [%d %d] %d\n", rec->fBitmap.width(), rec->fBitmap.height(), rec->fLockCount);
-            return (ID*)rec;
+            return rec;
         }
         rec = rec->fNext;
     }
     return NULL;
 }
 
+SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig,
+                                                        SkScalar scaleX,
+                                                        SkScalar scaleY,
+                                                        SkBitmap* scaled) {
+    if (0 == scaleX || 0 == scaleY) {
+        // degenerate, and the key we use for mipmaps
+        return NULL;
+    }
+
+    Rec* rec = this->findAndLock(orig, scaleX, scaleY);
+    if (rec) {
+        SkASSERT(NULL == rec->fMip);
+        SkASSERT(rec->fBitmap.pixelRef());
+        *scaled = rec->fBitmap;
+    }
+    return (ID*)rec;
+}
+
+SkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig,
+                                                           SkMipMap const ** mip) {
+    Rec* rec = this->findAndLock(orig, 0, 0);
+    if (rec) {
+        SkASSERT(rec->fMip);
+        SkASSERT(NULL == rec->fBitmap.pixelRef());
+        *mip = rec->fMip;
+    }
+    return (ID*)rec;
+}
+
 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig,
                                                        SkScalar scaleX,
                                                        SkScalar scaleY,
                                                        const SkBitmap& scaled) {
+    if (0 == scaleX || 0 == scaleY) {
+        // degenerate, and the key we use for mipmaps
+        return NULL;
+    }
+
     Key key;
     if (!key.init(orig, scaleX, scaleY)) {
         return NULL;
     }
-
+    
     Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
     this->addToHead(rec);
     SkASSERT(1 == rec->fLockCount);
+    
+    // We may (now) be overbudget, so see if we need to purge something.
+    this->purgeAsNeeded();
+    return (ID*)rec;
+}
 
-//    SkDebugf("Added: [%d %d]\n", rec->fBitmap.width(), rec->fBitmap.height());
-
+SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig,
+                                                          const SkMipMap* mip) {
+    Key key;
+    if (!key.init(orig, 0, 0)) {
+        return NULL;
+    }
+    
+    Rec* rec = SkNEW_ARGS(Rec, (key, mip));
+    this->addToHead(rec);
+    SkASSERT(1 == rec->fLockCount);
+    
     // We may (now) be overbudget, so see if we need to purge something.
     this->purgeAsNeeded();
     return (ID*)rec;
@@ -375,6 +435,12 @@
     return get_cache()->findAndLock(orig, scaleX, scaleY, scaled);
 }
 
+SkScaledImageCache::ID* SkScaledImageCache::FindAndLockMip(const SkBitmap& orig,
+                                                       SkMipMap const ** mip) {
+    SkAutoMutexAcquire am(gMutex);
+    return get_cache()->findAndLockMip(orig, mip);
+}
+
 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const SkBitmap& orig,
                                                        SkScalar scaleX,
                                                        SkScalar scaleY,
@@ -383,6 +449,12 @@
     return get_cache()->addAndLock(orig, scaleX, scaleY, scaled);
 }
 
+SkScaledImageCache::ID* SkScaledImageCache::AddAndLockMip(const SkBitmap& orig,
+                                                          const SkMipMap* mip) {
+    SkAutoMutexAcquire am(gMutex);
+    return get_cache()->addAndLockMip(orig, mip);
+}
+
 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) {
     SkAutoMutexAcquire am(gMutex);
     return get_cache()->unlock(id);