Revert "Revert "DeferredTextureImageData low-bit-depth/dithering support""

This reverts commit d7c681d6a7b154d276e275becc51685eac8705c2.

Reason for revert: New param already used in Chrome

Original change's description:
> Revert "DeferredTextureImageData low-bit-depth/dithering support"
> 
> This reverts commit 2c075e749d1f33dea06ad2710e15c9a1d60ebced.
> 
> Reason for revert: Breaking tests. e.g.: https://chromium-swarm.appspot.com/task?id=369dc44f62ce9510&refresh=10
> 
> Original change's description:
> > DeferredTextureImageData low-bit-depth/dithering support
> > 
> > Cause DeferredTextureImageData functionality to support low bit depth
> > (4444, 565) image formats (with dithering).
> > 
> > Bug: 720105
> > Change-Id: Ie3b5768ebc393d9b0a5322461c722bf37c80b791
> > Reviewed-on: https://skia-review.googlesource.com/18945
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > Commit-Queue: Eric Karl <ericrk@chromium.org>
> 
> TBR=bsalomon@google.com,ericrk@chromium.org
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 720105
> 
> Change-Id: I07aec722425efc62bc54f82cee9a19a9bf339f7b
> Reviewed-on: https://skia-review.googlesource.com/19039
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,reviews@skia.org,ericrk@chromium.org
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 720105

Change-Id: I91e690d0564f04209a2bd677de9ae9eb9c0f90d3
Reviewed-on: https://skia-review.googlesource.com/19041
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gm/deferredtextureimage.cpp b/gm/deferredtextureimage.cpp
index 9c1fe6a..db070fc 100644
--- a/gm/deferredtextureimage.cpp
+++ b/gm/deferredtextureimage.cpp
@@ -154,6 +154,13 @@
     DrawDeferredTextureImageData(canvas, &params);
 }
 
+DEF_SIMPLE_GM(deferred_texture_image_low_dithered, canvas, 512 + 512 + 30, 512 + 20) {
+    auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
+                                                           kLow_SkFilterQuality, 0,
+                                                           kARGB_4444_SkColorType);
+    DrawDeferredTextureImageData(canvas, &params);
+}
+
 DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
     sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
     if (!encodedImage) {
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index bc0597c..b896856 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -447,11 +447,15 @@
     /** Drawing params for which a deferred texture image data should be optimized. */
     struct DeferredTextureImageUsageParams {
         DeferredTextureImageUsageParams(const SkMatrix matrix, const SkFilterQuality quality,
-                                        int preScaleMipLevel)
-            : fMatrix(matrix), fQuality(quality), fPreScaleMipLevel(preScaleMipLevel) {}
+                                        int preScaleMipLevel,
+                                        SkColorType colorType = kN32_SkColorType)
+            : fMatrix(matrix), fQuality(quality), fPreScaleMipLevel(preScaleMipLevel),
+              fColorType(colorType) {}
         SkMatrix        fMatrix;
         SkFilterQuality fQuality;
         int             fPreScaleMipLevel;
+        SkColorType     fColorType;
+
     };
 
     /**
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp
index 865b3a6..5ad1939 100644
--- a/src/core/SkAutoPixmapStorage.cpp
+++ b/src/core/SkAutoPixmapStorage.cpp
@@ -14,6 +14,16 @@
     this->freeStorage();
 }
 
+SkAutoPixmapStorage& SkAutoPixmapStorage::operator=(SkAutoPixmapStorage&& other) {
+    this->fStorage = other.fStorage;
+    this->INHERITED::reset(other.info(), this->fStorage, other.rowBytes(), other.ctable());
+
+    other.fStorage = nullptr;
+    other.INHERITED::reset();
+
+    return *this;
+}
+
 size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) {
     size_t rb = info.minRowBytes();
     if (rowBytes) {
diff --git a/src/core/SkAutoPixmapStorage.h b/src/core/SkAutoPixmapStorage.h
index 66c5655..6342a41 100644
--- a/src/core/SkAutoPixmapStorage.h
+++ b/src/core/SkAutoPixmapStorage.h
@@ -17,6 +17,11 @@
     ~SkAutoPixmapStorage();
 
     /**
+    * Leave the moved-from object in a free-but-valid state.
+    */
+    SkAutoPixmapStorage& operator=(SkAutoPixmapStorage&& other);
+
+    /**
     *  Try to allocate memory for the pixels needed to match the specified Info. On success
     *  return true and fill out the pixmap to point to that memory. The storage will be freed
     *  when this object is destroyed, or if another call to tryAlloc() or alloc() is made.
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 55ceba0..4c89e8e 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -657,7 +657,8 @@
     SkAutoPixmapStorage pixmap;
     SkImageInfo info;
     size_t pixelSize = 0;
-    if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable()) {
+    if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable() &&
+        pixmap.info().colorType() == params[0].fColorType) {
         info = pixmap.info();
         pixelSize = SkAlign8(pixmap.getSafeSize());
         if (!dstColorSpace) {
@@ -680,24 +681,35 @@
                 info = info.makeColorSpace(nullptr);
             }
         }
-        if (kIndex_8_SkColorType == info.colorType()) {
-            // Force Index8 to be N32 instead. Index8 is unsupported in Ganesh.
-            info = info.makeColorType(kN32_SkColorType);
-        }
+        // Force color type to be the requested type.
+        info = info.makeColorType(params->fColorType);
         pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
         if (fillMode) {
-            pixmap.alloc(info);
+            // Always decode to N32 and convert to the requested type if necessary.
+            SkImageInfo decodeInfo = info.makeColorType(kN32_SkColorType);
+            SkAutoPixmapStorage decodePixmap;
+            decodePixmap.alloc(decodeInfo);
+
             if (isScaled) {
-                if (!this->scalePixels(pixmap, scaleFilterQuality,
+                if (!this->scalePixels(decodePixmap, scaleFilterQuality,
                                        SkImage::kDisallow_CachingHint)) {
                     return 0;
                 }
             } else {
-                if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
+                if (!this->readPixels(decodePixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
                     return 0;
                 }
             }
-            SkASSERT(!pixmap.ctable());
+            SkASSERT(!decodePixmap.ctable());
+
+            if (decodeInfo.colorType() != info.colorType()) {
+                pixmap.alloc(info);
+                // Convert and copy the decoded pixmap to the target pixmap.
+                decodePixmap.readPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 0,
+                                        0);
+            } else {
+                pixmap = std::move(decodePixmap);
+            }
         }
     }
     int mipMapLevelCount = 1;
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index c747b8e..a67756b 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1078,6 +1078,13 @@
         { createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
                         {SkMatrix::I(), kMedium_SkFilterQuality, 4}},
           kMedium_SkFilterQuality, 16, true},
+        // Create a images which are decoded to a 4444 backing.
+        { create_image,       {{SkMatrix::I(), kNone_SkFilterQuality, 0,kARGB_4444_SkColorType}},
+          kNone_SkFilterQuality, 1, true },
+        { create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0, kARGB_4444_SkColorType}},
+          kNone_SkFilterQuality, 1, true },
+        { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0, kARGB_4444_SkColorType}},
+          kNone_SkFilterQuality, 1, true },
     };