Revert "Revert "cache SkImage::Info calculation in lazypixelref""

This reverts commit 81eba32ab10f9210c742938819cf1218be5611c9.

ImageDecoder is changed to allow info to be NULL, since it is an output-only parameter.

R=scroggo@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk/src@11896 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/images/SkImageDecoder.cpp b/images/SkImageDecoder.cpp
index 3ee4112..89bd059 100644
--- a/images/SkImageDecoder.cpp
+++ b/images/SkImageDecoder.cpp
@@ -405,10 +405,6 @@
 bool SkImageDecoder::DecodeMemoryToTarget(const void* buffer, size_t size,
                                           SkImage::Info* info,
                                           const SkBitmapFactory::Target* target) {
-    if (NULL == info) {
-        return false;
-    }
-
     // FIXME: Just to get this working, implement in terms of existing
     // ImageDecoder calls.
     SkBitmap bm;
@@ -427,14 +423,17 @@
     // Now set info properly.
     // Since Config is SkBitmap::kARGB_8888_Config, SkBitmapToImageInfo
     // will always succeed.
-    SkAssertResult(SkBitmapToImageInfo(bm, info));
+    if (info) {
+        SkAssertResult(SkBitmapToImageInfo(bm, info));
+    }
 
     if (NULL == target) {
         return true;
     }
 
     if (target->fRowBytes != SkToU32(bm.rowBytes())) {
-        if (target->fRowBytes < SkImageMinRowBytes(*info)) {
+        size_t minRB = SkBitmap::ComputeRowBytes(bm.config(), bm.width());
+        if (target->fRowBytes < minRB) {
             SkDEBUGFAIL("Desired row bytes is too small");
             return false;
         }
diff --git a/lazy/SkLazyPixelRef.cpp b/lazy/SkLazyPixelRef.cpp
index 22d4b11..ad60892 100644
--- a/lazy/SkLazyPixelRef.cpp
+++ b/lazy/SkLazyPixelRef.cpp
@@ -37,6 +37,10 @@
     }
     SkASSERT(cache != NULL);
     cache->ref();
+
+    // mark as uninitialized -- all fields are -1
+    memset(&fLazilyCachedInfo, 0xFF, sizeof(fLazilyCachedInfo));
+        
     // Since this pixel ref bases its data on encoded data, it should never change.
     this->setImmutable();
 }
@@ -63,6 +67,18 @@
     return safeSize.is32() ? safeSize.get32() : 0;
 }
 
+const SkImage::Info* SkLazyPixelRef::getCachedInfo() {
+    if (fLazilyCachedInfo.fWidth < 0) {
+        SkImage::Info info;
+        fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
+        if (fErrorInDecoding) {
+            return NULL;
+        }
+        fLazilyCachedInfo = info;
+    }
+    return &fLazilyCachedInfo;
+}
+
 void* SkLazyPixelRef::onLockPixels(SkColorTable**) {
     if (fErrorInDecoding) {
         return NULL;
@@ -91,20 +107,15 @@
         sk_atomic_inc(&gCacheMisses);
 #endif
     }
-    SkImage::Info info;
+
     SkASSERT(fData != NULL && fData->size() > 0);
     if (NULL == target.fAddr) {
-        // Determine the size of the image in order to determine how much memory to allocate.
-        // FIXME: As an optimization, only do this part once.
-        fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
-        if (fErrorInDecoding) {
-            // We can only reach here if fCacheId was already set to UNINITIALIZED_ID, or if
-            // pinCache returned NULL, in which case it was reset to UNINITIALIZED_ID.
+        const SkImage::Info* info = this->getCachedInfo();
+        if (NULL == info) {
             SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
             return NULL;
         }
-
-        size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes);
+        size_t bytes = ComputeMinRowBytesAndSize(*info, &target.fRowBytes);
         target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId);
         if (NULL == target.fAddr) {
             // Space could not be allocated.
@@ -121,7 +132,7 @@
     }
     SkASSERT(target.fAddr != NULL);
     SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId);
-    fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target);
+    fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), NULL, &target);
     if (fErrorInDecoding) {
         fImageCache->throwAwayCache(fCacheId);
         fCacheId = SkImageCache::UNINITIALIZED_ID;
diff --git a/lazy/SkLazyPixelRef.h b/lazy/SkLazyPixelRef.h
index c51675d..8f7a751 100644
--- a/lazy/SkLazyPixelRef.h
+++ b/lazy/SkLazyPixelRef.h
@@ -71,12 +71,16 @@
     SkImageCache*               fImageCache;
     intptr_t                    fCacheId;
     size_t                      fRowBytes;
+    SkImage::Info               fLazilyCachedInfo;
 
 #if LAZY_CACHE_STATS
     static int32_t              gCacheHits;
     static int32_t              gCacheMisses;
 #endif
 
+    // lazily initialized our cached info. Returns NULL on failure.
+    const SkImage::Info* getCachedInfo();
+
     typedef SkPixelRef INHERITED;
 };