SkImage method for detecting lazy decoding

BUG=skia:4224
R=reed@google.com

Review URL: https://codereview.chromium.org/1305453007
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 2a62135..5b9e203 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -288,6 +288,12 @@
      */
     bool asLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
     
+    /**
+     *  Returns true if the image is backed by an image-generator or other src that creates
+     *  (and caches) its pixels / texture on-demand.
+     */
+    bool isLazyGenerated() const;
+
 protected:
     SkImage(int width, int height, uint32_t uniqueID);
 
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index 5d1aef7..0d9182a 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -265,6 +265,11 @@
 
     virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return NULL; }
 
+    /**
+     *  Returns true if the pixels are generated on-the-fly (when required).
+     */
+    bool isLazyGenerated() const { return this->onIsLazyGenerated(); }
+
 protected:
     /**
      *  On success, returns true and fills out the LockRec for the pixels. On
@@ -318,6 +323,8 @@
 
     virtual bool onRequestLock(const LockRequest&, LockResult*);
 
+    virtual bool onIsLazyGenerated() const { return false; }
+
     /** Return the mutex associated with this pixelref. This value is assigned
         in the constructor, and cannot change during the lifetime of the object.
     */
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 9c996dc..715b4f4 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -287,6 +287,10 @@
     return NewFromGenerator(SkImageGenerator::NewFromPicture(dimensions, picture, matrix, paint));
 }
 
+bool SkImage::isLazyGenerated() const {
+    return as_IB(this)->onIsLazyGenerated();
+}
+
 //////////////////////////////////////////////////////////////////////////////////////
 
 #if !SK_SUPPORT_GPU
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 38f9906..46cd3de 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -60,7 +60,7 @@
 
     virtual SkShader* onNewShader(SkShader::TileMode,
                                   SkShader::TileMode,
-                                  const SkMatrix* localMatrix) const { return NULL; };
+                                  const SkMatrix* localMatrix) const { return NULL; }
 
     // newWidth > 0, newHeight > 0, subset either NULL or a proper subset of this bounds
     virtual SkImage* onNewImage(int newWidth, int newHeight, const SkIRect* subset,
@@ -69,6 +69,8 @@
 
     virtual bool onAsLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
 
+    virtual bool onIsLazyGenerated() const { return false; }
+
 private:
     const SkSurfaceProps fProps;
 
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 120c397..51bc6f0 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -93,6 +93,10 @@
         SkASSERT(fBitmap.isImmutable());
     }
 
+    bool onIsLazyGenerated() const override {
+        return fBitmap.pixelRef() && fBitmap.pixelRef()->isLazyGenerated();
+    }
+
 private:
     SkImage_Raster() : INHERITED(0, 0, kNeedNewImageUniqueID, NULL) {
         fBitmap.setImmutable();
diff --git a/src/lazy/SkCachingPixelRef.h b/src/lazy/SkCachingPixelRef.h
index 25fde0a..818db22 100644
--- a/src/lazy/SkCachingPixelRef.h
+++ b/src/lazy/SkCachingPixelRef.h
@@ -50,6 +50,8 @@
         return fImageGenerator->refEncodedData();
     }
 
+    bool onIsLazyGenerated() const override { return true; }
+
 private:
     SkImageGenerator* const fImageGenerator;
     bool                    fErrorInDecoding;
diff --git a/src/lazy/SkDiscardablePixelRef.h b/src/lazy/SkDiscardablePixelRef.h
index e8451ee..3b38fa6 100644
--- a/src/lazy/SkDiscardablePixelRef.h
+++ b/src/lazy/SkDiscardablePixelRef.h
@@ -36,6 +36,8 @@
         return fGenerator->refEncodedData();
     }
 
+    bool onIsLazyGenerated() const override { return true; }
+
 private:
     SkImageGenerator* const fGenerator;
     SkDiscardableMemory::Factory* const fDMFactory;
diff --git a/tests/CachedDecodingPixelRefTest.cpp b/tests/CachedDecodingPixelRefTest.cpp
index 0e9b18e..c69cd96 100644
--- a/tests/CachedDecodingPixelRefTest.cpp
+++ b/tests/CachedDecodingPixelRefTest.cpp
@@ -326,6 +326,7 @@
         }
         REPORTER_ASSERT(r, TestImageGenerator::Width() == image->width());
         REPORTER_ASSERT(r, TestImageGenerator::Height() == image->height());
+        REPORTER_ASSERT(r, image->isLazyGenerated());
 
         SkBitmap bitmap;
         bitmap.allocN32Pixels(TestImageGenerator::Width(), TestImageGenerator::Height());
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index f5e1abc..1c173da 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -229,10 +229,11 @@
         void (*fMakeProc)(SkBitmap*);
         bool fExpectPeekSuccess;
         bool fExpectSharedID;
+        bool fExpectLazy;
     } rec[] = {
-        { make_bitmap_lazy,         false,  true  },
-        { make_bitmap_mutable,      true,   false },
-        { make_bitmap_immutable,    true,   true  },
+        { make_bitmap_lazy,         false,  true,  true  },
+        { make_bitmap_mutable,      true,   false, false },
+        { make_bitmap_immutable,    true,   true,  false },
     };
 
     for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
@@ -247,6 +248,9 @@
 
         const bool peekSuccess = image->peekPixels(&pmap);
         REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
+
+        const bool lazy = image->isLazyGenerated();
+        REPORTER_ASSERT(reporter, lazy == rec[i].fExpectLazy);
     }
 }