Stop wrapping images backed by generators as bitmaps in SkGpuDevice (except when tiling)

Review URL: https://codereview.chromium.org/1510903002
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp
index f4a2ab7..9074924 100644
--- a/src/core/SkImageCacherator.cpp
+++ b/src/core/SkImageCacherator.cpp
@@ -17,6 +17,7 @@
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrGpuResourcePriv.h"
+#include "GrImageIDTextureAdjuster.h"
 #include "GrResourceKey.h"
 #include "GrTextureParams.h"
 #include "GrYUVProvider.h"
@@ -289,60 +290,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-#include "GrTextureParamsAdjuster.h"
-
-class Cacherator_GrTextureMaker : public GrTextureMaker {
-public:
-    Cacherator_GrTextureMaker(GrContext* context, SkImageCacherator* cacher, const SkImage* client,
-                              SkImage::CachingHint chint)
-        : INHERITED(context, cacher->info().width(), cacher->info().height())
-        , fCacher(cacher)
-        , fClient(client)
-        , fCachingHint(chint)
-    {
-        if (client) {
-            GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),
-                                 SkIRect::MakeWH(this->width(), this->height()));
-        }
-    }
-
-protected:
-    // TODO: consider overriding this, for the case where the underlying generator might be
-    //       able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
-    //          GrTexture* generateTextureForParams(const CopyParams&) override;
-
-    GrTexture* refOriginalTexture() override {
-        return fCacher->lockTexture(this->context(), fOriginalKey, fClient, fCachingHint);
-    }
-
-    void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override {
-        if (fOriginalKey.isValid()) {
-            MakeCopyKeyFromOrigKey(fOriginalKey, stretch, paramsCopyKey);
-        }
-    }
-
-    void didCacheCopy(const GrUniqueKey& copyKey) override {
-        if (fClient) {
-            as_IB(fClient)->notifyAddedToCache();
-        }
-    }
-
-private:
-    SkImageCacherator*      fCacher;
-    const SkImage*          fClient;
-    GrUniqueKey             fOriginalKey;
-    SkImage::CachingHint    fCachingHint;
-
-    typedef GrTextureMaker INHERITED;
-};
-
 GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, const GrTextureParams& params,
                                             const SkImage* client, SkImage::CachingHint chint) {
     if (!ctx) {
         return nullptr;
     }
 
-    return Cacherator_GrTextureMaker(ctx, this, client, chint).refTextureForParams(params);
+    return GrImageTextureMaker(ctx, this, client, chint).refTextureForParams(params);
 }
 
 #else
diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h
index bce3967..42b93f6 100644
--- a/src/core/SkImageCacherator.h
+++ b/src/core/SkImageCacherator.h
@@ -95,7 +95,7 @@
     const SkIPoint      fOrigin;
     const uint32_t      fUniqueID;
 
-    friend class Cacherator_GrTextureMaker;
+    friend class GrImageTextureMaker;
 };
 
 #endif
diff --git a/src/gpu/GrImageIDTextureAdjuster.cpp b/src/gpu/GrImageIDTextureAdjuster.cpp
index c37c022..a9189f6 100644
--- a/src/gpu/GrImageIDTextureAdjuster.cpp
+++ b/src/gpu/GrImageIDTextureAdjuster.cpp
@@ -12,6 +12,7 @@
 #include "SkBitmap.h"
 #include "SkGrPriv.h"
 #include "SkImage_Base.h"
+#include "SkImageCacherator.h"
 #include "SkPixelRef.h"
 
 GrBitmapTextureAdjuster::GrBitmapTextureAdjuster(const SkBitmap* bmp)
@@ -96,3 +97,33 @@
 void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey) {
     GrInstallBitmapUniqueKeyInvalidator(copyKey, fBitmap.pixelRef());
 }
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrImageTextureMaker::GrImageTextureMaker(GrContext* context, SkImageCacherator* cacher,
+                                         const SkImage* client, SkImage::CachingHint chint)
+    : INHERITED(context, cacher->info().width(), cacher->info().height())
+    , fCacher(cacher)
+    , fClient(client)
+    , fCachingHint(chint) {
+    if (client) {
+        GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),
+                             SkIRect::MakeWH(this->width(), this->height()));
+    }
+}
+
+GrTexture* GrImageTextureMaker::refOriginalTexture() {
+    return fCacher->lockTexture(this->context(), fOriginalKey, fClient, fCachingHint);
+}
+
+void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
+    if (fOriginalKey.isValid() && SkImage::kAllow_CachingHint == fCachingHint) {
+        MakeCopyKeyFromOrigKey(fOriginalKey, stretch, paramsCopyKey);
+    }
+}
+
+void GrImageTextureMaker::didCacheCopy(const GrUniqueKey& copyKey) {
+    if (fClient) {
+        as_IB(fClient)->notifyAddedToCache();
+    }
+}
diff --git a/src/gpu/GrImageIDTextureAdjuster.h b/src/gpu/GrImageIDTextureAdjuster.h
index a20902e..d8510fe 100644
--- a/src/gpu/GrImageIDTextureAdjuster.h
+++ b/src/gpu/GrImageIDTextureAdjuster.h
@@ -9,9 +9,11 @@
 #define GrImageIDTextureAdjuster_DEFINED
 
 #include "GrTextureParamsAdjuster.h"
+#include "SkImage.h"
 
 class SkBitmap;
 class SkImage_Base;
+class SkImageCacherator;
 
 /** Implementation for texture-backed SkBitmaps. The bitmap must stay in scope and unmodified 
     while this object exists. */
@@ -66,4 +68,29 @@
     typedef GrTextureMaker INHERITED;
 };
 
+/** This class manages the conversion of generator-backed images to GrTextures. If the caching hint
+    is kAllow the image's ID is used for the cache key. */
+class GrImageTextureMaker : public GrTextureMaker {
+public:
+    GrImageTextureMaker(GrContext* context, SkImageCacherator* cacher, const SkImage* client,
+                        SkImage::CachingHint chint);
+
+protected:
+    // TODO: consider overriding this, for the case where the underlying generator might be
+    //       able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
+    //          GrTexture* generateTextureForParams(const CopyParams&) override;
+
+    GrTexture* refOriginalTexture() override;
+    void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
+    void didCacheCopy(const GrUniqueKey& copyKey) override;
+
+private:
+    SkImageCacherator*      fCacher;
+    const SkImage*          fClient;
+    GrUniqueKey             fOriginalKey;
+    SkImage::CachingHint    fCachingHint;
+
+    typedef GrTextureMaker INHERITED;
+};
+
 #endif
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 17e4468..2545313 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -27,6 +27,7 @@
 #include "SkGr.h"
 #include "SkGrPriv.h"
 #include "SkImage_Base.h"
+#include "SkImageCacherator.h"
 #include "SkImageFilter.h"
 #include "SkLayerInfo.h"
 #include "SkMaskFilter.h"
@@ -1399,43 +1400,36 @@
                                filter, ctx, result, offset);
 }
 
-static bool wrap_as_bm(GrContext* ctx, const SkImage* image, SkBitmap* bm) {
-    // TODO: It is wrong to assume these texture params here.
-    SkAutoTUnref<GrTexture> tex(as_IB(image)->asTextureRef(ctx, GrTextureParams::ClampNoFilter()));
-    if (tex) {
-        GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
-        return true;
-    } else {
-        return as_IB(image)->getROPixels(bm);
-    }
-}
-
 void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
                             const SkPaint& paint) {
-    SkBitmap bm;
+    SkMatrix viewMatrix = *draw.fMatrix;
+    viewMatrix.preTranslate(x, y);
     if (GrTexture* tex = as_IB(image)->peekTexture()) {
         CHECK_SHOULD_DRAW(draw);
-        SkMatrix viewMatrix = *draw.fMatrix;
-        viewMatrix.preTranslate(x, y);
         bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config());
         GrImageTextureAdjuster adjuster(as_IB(image));
         this->drawTextureProducer(&adjuster, alphaOnly, nullptr, nullptr,
                                   SkCanvas::kFast_SrcRectConstraint, viewMatrix, fClip, paint);
         return;
     } else {
+        SkBitmap bm;
         if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstraint,
                                   paint.getFilterQuality(), *draw.fMatrix)) {
             // only support tiling as bitmap at the moment, so force raster-version
             if (!as_IB(image)->getROPixels(&bm)) {
                 return;
             }
-        } else {
-            if (!wrap_as_bm(this->context(), image, &bm)) {
-                return;
-            }
+            this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
+        } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
+            CHECK_SHOULD_DRAW(draw);
+            GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
+            bool alphaOnly = kAlpha_8_SkColorType == cacher->info().colorType();
+            this->drawTextureProducer(&maker, alphaOnly, nullptr, nullptr,
+                                      SkCanvas::kFast_SrcRectConstraint, viewMatrix, fClip, paint);
+        } else if (as_IB(image)->getROPixels(&bm)) {
+            this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
         }
     }
-    this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
 }
 
 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
@@ -1450,20 +1444,35 @@
         return;
     }
     SkBitmap bm;
-    SkMatrix viewMatrix = *draw.fMatrix;
-    viewMatrix.preScale(dst.width() / (src ? src->width() : image->width()),
-                        dst.height() / (src ? src->height() : image->height()));
-    if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), viewMatrix)) {
+    SkMatrix totalMatrix = *draw.fMatrix;
+    totalMatrix.preScale(dst.width() / (src ? src->width() : image->width()),
+                         dst.height() / (src ? src->height() : image->height()));
+    if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(), totalMatrix)) {
         // only support tiling as bitmap at the moment, so force raster-version
         if (!as_IB(image)->getROPixels(&bm)) {
             return;
         }
-    } else {
-        if (!wrap_as_bm(this->context(), image, &bm)) {
-            return;
-        }
+        this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
+    } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
+        CHECK_SHOULD_DRAW(draw);
+        GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
+        bool alphaOnly = kAlpha_8_SkColorType == cacher->info().colorType();
+        this->drawTextureProducer(&maker, alphaOnly, src, &dst, constraint, *draw.fMatrix,
+                                  fClip, paint);
+    } else if (as_IB(image)->getROPixels(&bm)) {
+        this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
     }
-    this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
+}
+
+static bool wrap_as_bm(GrContext* ctx, const SkImage* image, SkBitmap* bm) {
+    // TODO: It is wrong to assume these texture params here.
+    SkAutoTUnref<GrTexture> tex(as_IB(image)->asTextureRef(ctx, GrTextureParams::ClampNoFilter()));
+    if (tex) {
+        GrWrapTextureInBitmap(tex, image->width(), image->height(), image->isOpaque(), bm);
+        return true;
+    } else {
+        return as_IB(image)->getROPixels(bm);
+    }
 }
 
 void SkGpuDevice::drawImageNine(const SkDraw& draw, const SkImage* image,
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 5cb6a48..321dcaa 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -15,6 +15,7 @@
 #include <new>
 
 class GrTextureParams;
+class SkImageCacherator;
 
 enum {
     kNeedNewImageUniqueID = 0
@@ -32,6 +33,7 @@
                               int srcX, int srcY, CachingHint) const;
 
     virtual GrTexture* peekTexture() const { return nullptr; }
+    virtual SkImageCacherator* peekCacherator() const { return nullptr; }
 
     // return a read-only copy of the pixels. We promise to not modify them,
     // but only inspect them (or encode them).
diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp
index fbde92d..6671dcd 100644
--- a/src/image/SkImage_Generator.cpp
+++ b/src/image/SkImage_Generator.cpp
@@ -23,6 +23,7 @@
 
     bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY, CachingHint) const override;
     const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const override;
+    SkImageCacherator* peekCacherator() const override { return fCache; }
     SkData* onRefEncoded() const override;
     bool isOpaque() const override { return fCache->info().isOpaque(); }
     SkImage* onNewSubset(const SkIRect&) const override;