Roll external/skia bbb24101e..ba651682a (4 commits)

https://skia.googlesource.com/skia.git/+log/bbb24101e..ba651682a

2018-10-05 brianosman@google.com Fix two bugs in GPU special image read-back
2018-10-05 fmalita@chromium.org [skottie] Remove temporary ResourceProvider::load() fallback
2018-10-05 reed@google.com isolate users of SkFindAndPlaceGlyph.h
2018-10-05 robertphillips@google.com Expose the SkYUVAIndex version of the SkImage factories

The AutoRoll server is located here: https://autoroll-internal.skia.org/r/android-master-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.

Test: Presubmit checks will test this change.
Change-Id: I011442c08f4ef04d58500d27139a559e49f353d4
Exempt-From-Owner-Approval: The autoroll bot does not require owner approval.
diff --git a/docs/SkImage_Reference.bmh b/docs/SkImage_Reference.bmh
index 6df8bc8..35261dc 100644
--- a/docs/SkImage_Reference.bmh
+++ b/docs/SkImage_Reference.bmh
@@ -453,7 +453,7 @@
    return;
 }
 auto debugster = [](SkImage::ReleaseContext releaseContext) -> void {
- // broken 
+ // broken
  //   *((int *) releaseContext) += 128;
 };
 int x = 0;
@@ -624,10 +624,101 @@
 
 # ------------------------------------------------------------------------------
 
+#Method static sk_sp<SkImage> MakeFromYUVATexturesCopy(GrContext* context,
+                                                   SkYUVColorSpace yuvColorSpace,
+                                                   const GrBackendTexture yuvaTextures[],
+                                                   const SkYUVAIndex yuvaIndices[4],
+                                                   SkISize imageSize,
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr)
+#In Constructor
+#Line # creates Image from YUV_ColorSpace data ##
+Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA image.
+
+#Param context         GPU context ##
+#Param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                    kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                    kRec709_SkYUVColorSpace
+##
+#Param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                       possibly interleaved, YUVA planes
+##
+#Param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
+                       (in the specified texture) maps to each of Y, U, V, and A.
+##
+#Param imageSize       size of the resulting image ##
+#Param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                                                              kTopLeft_GrSurfaceOrigin
+##
+#Param imageColorSpace range of colors of the resulting image; may be nullptr ##
+
+#Return                created SkImage, or nullptr ##
+
+# seems too complicated to create an example for this
+#ToDo
+should this be moved to chrome only?
+##
+
+#NoExample
+##
+
+#SeeAlso MakeFromYUVATexturesCopyWithExternalBackend
+
+#Method ##
+
+# ------------------------------------------------------------------------------
+
+#Method static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackend(
+            GrContext* context,
+            SkYUVColorSpace yuvColorSpace,
+            const GrBackendTexture yuvaTextures[],
+            const SkYUVAIndex yuvaIndices[4],
+            SkISize imageSize,
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr)
+#In Constructor
+#Line # creates Image from planar YUV_ColorSpace, stored in texture ##
+
+Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
+image. backendTexture is used to store the result of the flattening.
+
+#Param context         GPU context ##
+#Param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                    kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                    kRec709_SkYUVColorSpace
+##
+#Param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                       possibly interleaved, YUVA planes
+##
+#Param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
+                       (in the specified texture) maps to each of Y, U, V, and A.
+##
+#Param imageSize       size of the resulting image ##
+#Param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                                                              kTopLeft_GrSurfaceOrigin
+##
+#Param backendTexture  the resource that stores the final pixels ##
+#Param imageColorSpace range of colors of the resulting image; may be nullptr ##
+
+#Return                created SkImage, or nullptr ##
+
+# seems too complicated to create an example for this
+#ToDo
+should this be moved to chrome only?
+##
+
+#NoExample
+##
+
+#SeeAlso MakeFromYUVATexturesCopy
+
+#Method ##
+
 #Method static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
                                                   const GrBackendTexture yuvTextures[3],
-                                                  GrSurfaceOrigin surfaceOrigin,
-                                                  sk_sp<SkColorSpace> colorSpace = nullptr)
+                                                  GrSurfaceOrigin imageOrigin,
+                                                  sk_sp<SkColorSpace> imageColorSpace = nullptr)
 #In Constructor
 #Line # creates Image from YUV_ColorSpace data in three planes ##
 
@@ -639,9 +730,9 @@
 #Param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
                               kRec709_SkYUVColorSpace
 ##
-#Param yuvTextures  array of YUV textures on GPU ##
-#Param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
-#Param colorSpace  range of colors; may be nullptr ##
+#Param yuvTextures     array of YUV textures on GPU ##
+#Param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
+#Param imageColorSpace range of colors; may be nullptr ##
 
 #Return created Image, or nullptr ##
 
@@ -653,14 +744,16 @@
 #NoExample
 ##
 
-#SeeAlso MakeFromYUVTexturesCopyWithExternalBackend MakeFromNV12TexturesCopy
+#SeeAlso MakeFromYUVTexturesCopyWithExternalBackend MakeFromNV12TexturesCopy MakeFromYUVATexturesCopy
 
 #Method ##
 
+# ------------------------------------------------------------------------------
+
 #Method static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
         GrContext* context, SkYUVColorSpace yuvColorSpace,
-        const GrBackendTexture yuvTextures[3], GrSurfaceOrigin surfaceOrigin,
-        const GrBackendTexture backendTexture, sk_sp<SkColorSpace> colorSpace = nullptr);
+        const GrBackendTexture yuvTextures[3], GrSurfaceOrigin imageOrigin,
+        const GrBackendTexture& backendTexture, sk_sp<SkColorSpace> imageColorSpace = nullptr);
 #In Constructor
 #Line # creates Image from planar YUV_ColorSpace, stored in texture ##
 
@@ -669,14 +762,14 @@
 yuvTextures[0] and stores pixels in backendTexture. yuvColorSpace describes how YUV colors
 convert to RGB colors.
 
-#Param context        GPU_Context ##
-#Param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                            kRec709_SkYUVColorSpace
+#Param context         GPU_Context ##
+#Param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
 ##
-#Param yuvTextures    array of YUV textures on GPU ##
-#Param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
-#Param backendTexture the resource that stores the final pixels ##
-#Param colorSpace     range of colors; may be nullptr ##
+#Param yuvTextures     array of YUV textures on GPU ##
+#Param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
+#Param backendTexture  the resource that stores the final pixels ##
+#Param imageColorSpace range of colors; may be nullptr ##
 
 #Return               created SkImage, or nullptr ##
 
@@ -688,7 +781,7 @@
 #NoExample
 ##
 
-#SeeAlso MakeFromYUVTexturesCopy MakeFromNV12TexturesCopy
+#SeeAlso MakeFromYUVTexturesCopy MakeFromNV12TexturesCopy MakeFromYUVATexturesCopyWithExternalBackend
 
 #Method ##
 
@@ -697,8 +790,8 @@
 #Method static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext* context,
                                                    SkYUVColorSpace yuvColorSpace,
                                                    const GrBackendTexture nv12Textures[2],
-                                                   GrSurfaceOrigin surfaceOrigin,
-                                                   sk_sp<SkColorSpace> colorSpace = nullptr)
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr)
 #In Constructor
 #Line # creates Image from YUV_ColorSpace data in three planes ##
 
@@ -709,13 +802,13 @@
 Returned Image has the dimensions nv12Textures[2].
 yuvColorSpace describes how YUV colors convert to RGB colors.
 
-#Param context  GPU_Context ##
-#Param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                              kRec709_SkYUVColorSpace
+#Param context         GPU_Context ##
+#Param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
 ##
-#Param nv12Textures  array of YUV textures on GPU ##
-#Param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
-#Param colorSpace  range of colors; may be nullptr ##
+#Param nv12Textures    array of YUV textures on GPU ##
+#Param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
+#Param imageColorSpace range of colors; may be nullptr ##
 
 #Return created Image, or nullptr ##
 
@@ -727,7 +820,7 @@
 #NoExample
 ##
 
-#SeeAlso MakeFromNV12TexturesCopyWithExternalBackend MakeFromYUVTexturesCopy
+#SeeAlso MakeFromNV12TexturesCopyWithExternalBackend MakeFromYUVTexturesCopy MakeFromYUVATexturesCopy
 
 #Method ##
 
@@ -735,9 +828,9 @@
             GrContext* context,
             SkYUVColorSpace yuvColorSpace,
             const GrBackendTexture nv12Textures[2],
-            GrSurfaceOrigin surfaceOrigin,
-            const GrBackendTexture backendTexture,
-            sk_sp<SkColorSpace> colorSpace = nullptr);
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
 #In Constructor
 #Line # creates Image from planar YUV_ColorSpace, stored in texture ##
 
@@ -748,14 +841,14 @@
 Returned Image has the dimensions nv12Textures[2] and stores pixels in backendTexture.
 yuvColorSpace describes how YUV colors convert to RGB colors.
 
-#Param context  GPU_Context ##
-#Param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                              kRec709_SkYUVColorSpace
+#Param context         GPU_Context ##
+#Param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
 ##
-#Param nv12Textures  array of YUV textures on GPU ##
-#Param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
-#Param backendTexture the resource that stores the final pixels ##
-#Param colorSpace  range of colors; may be nullptr ##
+#Param nv12Textures    array of YUV textures on GPU ##
+#Param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin ##
+#Param backendTexture  the resource that stores the final pixels ##
+#Param imageColorSpace range of colors; may be nullptr ##
 
 #Return created Image, or nullptr ##
 
@@ -767,7 +860,7 @@
 #NoExample
 ##
 
-#SeeAlso MakeFromNV12TexturesCopy MakeFromYUVTexturesCopy
+#SeeAlso MakeFromNV12TexturesCopy MakeFromYUVTexturesCopy MakeFromYUVATexturesCopyWithExternalBackend
 
 #Method ##
 
diff --git a/docs/undocumented.bmh b/docs/undocumented.bmh
index bb9fc88..ad056fa 100644
--- a/docs/undocumented.bmh
+++ b/docs/undocumented.bmh
@@ -726,6 +726,11 @@
 ##
 ##
 
+#Topic YUV_Planes
+#Class SkYUVAIndex
+##
+##
+
 #Topic RenderTarget
 #Class GrBackendRenderTarget
     #Method bool isValid() const
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 79efdd8..cf9e02f 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -43,6 +43,8 @@
 class GrContextThreadSafeProxy;
 class GrTexture;
 
+struct SkYUVAIndex;
+
 /** \class SkImage
     SkImage describes a two dimensional array of pixels to draw. The pixels may be
     decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,
@@ -325,22 +327,75 @@
                                                  SkAlphaType alphaType = kPremul_SkAlphaType,
                                                  sk_sp<SkColorSpace> colorSpace = nullptr);
 
+    /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
+        image.
+
+        @param context         GPU context
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvTextures     array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
+                               (in the specified texture) maps to each of Y, U, V, and A.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVATexturesCopy(GrContext* context,
+                                                   SkYUVColorSpace yuvColorSpace,
+                                                   const GrBackendTexture yuvaTextures[],
+                                                   const SkYUVAIndex yuvaIndices[4],
+                                                   SkISize imageSize,
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
+        image. 'backendTexture' is used to store the result of the flattening.
+
+        @param context         GPU context
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvTextures     array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture (in 'yuvaTextures') and channel
+                               (in the specified texture) maps to each of Y, U, V, and A.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param backendTexture  the resource that stores the final pixels
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackend(
+            GrContext* context,
+            SkYUVColorSpace yuvColorSpace,
+            const GrBackendTexture yuvaTextures[],
+            const SkYUVAIndex yuvaIndices[4],
+            SkISize imageSize,
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
     /** Creates SkImage from copy of yuvTextures, an array of textures on GPU.
         yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions
         yuvTextures[0]. yuvColorSpace describes how YUV colors convert to RGB colors.
 
-        @param context        GPU context
-        @param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                              kRec709_SkYUVColorSpace
-        @param yuvTextures    array of YUV textures on GPU
-        @param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
-        @param colorSpace     range of colors; may be nullptr
-        @return               created SkImage, or nullptr
+        @param context         GPU context
+        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
+        @param yuvTextures     array of YUV textures on GPU
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors; may be nullptr
+        @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
                                                   const GrBackendTexture yuvTextures[3],
-                                                  GrSurfaceOrigin surfaceOrigin,
-                                                  sk_sp<SkColorSpace> colorSpace = nullptr);
+                                                  GrSurfaceOrigin imageOrigin,
+                                                  sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
     /** Creates SkImage from copy of yuvTextures, an array of textures on GPU.
         yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions
@@ -351,15 +406,15 @@
         @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
                                kRec709_SkYUVColorSpace
         @param yuvTextures     array of YUV textures on GPU
-        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @param backendTexture  the resource that stores the final pixels
-        @param colorSpace      range of colors; may be nullptr
+        @param imageColorSpace range of colors; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
             GrContext* context, SkYUVColorSpace yuvColorSpace,
-            const GrBackendTexture yuvTextures[3], GrSurfaceOrigin surfaceOrigin,
-            const GrBackendTexture backendTexture, sk_sp<SkColorSpace> colorSpace = nullptr);
+            const GrBackendTexture yuvTextures[3], GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture, sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
     /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
         nv12Textures[0] contains pixels for YUV component y plane.
@@ -368,19 +423,19 @@
         Returned SkImage has the dimensions nv12Textures[2].
         yuvColorSpace describes how YUV colors convert to RGB colors.
 
-        @param context        GPU context
-        @param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
-                              kRec709_SkYUVColorSpace
-        @param nv12Textures   array of YUV textures on GPU
-        @param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
-        @param colorSpace     range of colors; may be nullptr
-        @return               created SkImage, or nullptr
+        @param context         GPU context
+        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
+        @param nv12Textures    array of YUV textures on GPU
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors; may be nullptr
+        @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext* context,
                                                    SkYUVColorSpace yuvColorSpace,
                                                    const GrBackendTexture nv12Textures[2],
-                                                   GrSurfaceOrigin surfaceOrigin,
-                                                   sk_sp<SkColorSpace> colorSpace = nullptr);
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
     /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
         nv12Textures[0] contains pixels for YUV component y plane.
@@ -393,18 +448,18 @@
         @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
                                kRec709_SkYUVColorSpace
         @param nv12Textures    array of YUV textures on GPU
-        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
         @param backendTexture  the resource that stores the final pixels
-        @param colorSpace      range of colors; may be nullptr
+        @param imageColorSpace range of colors; may be nullptr
         @return                created SkImage, or nullptr
     */
     static sk_sp<SkImage> MakeFromNV12TexturesCopyWithExternalBackend(
             GrContext* context,
             SkYUVColorSpace yuvColorSpace,
             const GrBackendTexture nv12Textures[2],
-            GrSurfaceOrigin surfaceOrigin,
-            const GrBackendTexture backendTexture,
-            sk_sp<SkColorSpace> colorSpace = nullptr);
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
 
     enum class BitDepth {
         kU8,  //!< uses 8-bit unsigned int per color component
diff --git a/modules/skottie/src/Skottie.cpp b/modules/skottie/src/Skottie.cpp
index e4223cc..3faca99 100644
--- a/modules/skottie/src/Skottie.cpp
+++ b/modules/skottie/src/Skottie.cpp
@@ -10,7 +10,6 @@
 #include "SkCanvas.h"
 #include "SkData.h"
 #include "SkFontMgr.h"
-#include "SkImage.h"
 #include "SkMakeUnique.h"
 #include "SkOSPath.h"
 #include "SkPaint.h"
@@ -247,23 +246,7 @@
 }
 
 sk_sp<ImageAsset> ResourceProvider::loadImageAsset(const char path[], const char name[]) const {
-    // Legacy API fallback.  TODO: remove after clients get updated.
-    class StaticImageAsset final : public ImageAsset {
-    public:
-        explicit StaticImageAsset(sk_sp<SkImage> img) : fImage(std::move(img)) {}
-
-        bool isMultiFrame() override { return false; }
-
-        sk_sp<SkImage> getFrame(float) override { return fImage; }
-
-    private:
-        sk_sp<SkImage> fImage;
-    };
-
-    auto image = SkImage::MakeFromEncoded(this->load(path, name));
-
-    return image ? sk_make_sp<StaticImageAsset>(std::move(image))
-                 : nullptr;
+    return nullptr;
 }
 
 sk_sp<SkData> ResourceProvider::loadFont(const char[], const char[]) const {
diff --git a/src/core/SkBitmapCache.cpp b/src/core/SkBitmapCache.cpp
index 61ef6d4..8170cf6 100644
--- a/src/core/SkBitmapCache.cpp
+++ b/src/core/SkBitmapCache.cpp
@@ -51,10 +51,10 @@
     return SkIRect::MakeWH(image->width(), image->height());
 }
 
-SkBitmapCacheDesc SkBitmapCacheDesc::Make(uint32_t imageID, int origWidth, int origHeight) {
+SkBitmapCacheDesc SkBitmapCacheDesc::Make(uint32_t imageID, const SkIRect& subset) {
     SkASSERT(imageID);
-    SkASSERT(origWidth > 0 && origHeight > 0);
-    return { imageID, {0, 0, origWidth, origHeight} };
+    SkASSERT(subset.width() > 0 && subset.height() > 0);
+    return { imageID, subset };
 }
 
 SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm) {
diff --git a/src/core/SkBitmapCache.h b/src/core/SkBitmapCache.h
index 27e45fd..3909f73 100644
--- a/src/core/SkBitmapCache.h
+++ b/src/core/SkBitmapCache.h
@@ -30,9 +30,7 @@
 
     static SkBitmapCacheDesc Make(const SkBitmap&);
     static SkBitmapCacheDesc Make(const SkImage*);
-
-    // Use with care -- width/height must match the original bitmap/image
-    static SkBitmapCacheDesc Make(uint32_t genID, int origWidth, int origHeight);
+    static SkBitmapCacheDesc Make(uint32_t genID, const SkIRect& subset);
 };
 
 class SkBitmapCache {
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index ae97d05..cadf851 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -15,7 +15,6 @@
 #include "SkColorData.h"
 #include "SkDevice.h"
 #include "SkDrawProcs.h"
-#include "SkFindAndPlaceGlyph.h"
 #include "SkMaskFilterBase.h"
 #include "SkMacros.h"
 #include "SkMatrix.h"
diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp
index 774f4f6..f466ecf 100644
--- a/src/core/SkGlyphRunPainter.cpp
+++ b/src/core/SkGlyphRunPainter.cpp
@@ -19,7 +19,6 @@
 #include "SkDevice.h"
 #include "SkDistanceFieldGen.h"
 #include "SkDraw.h"
-#include "SkFindAndPlaceGlyph.h"
 #include "SkGlyphCache.h"
 #include "SkMaskFilter.h"
 #include "SkPaintPriv.h"
@@ -27,6 +26,22 @@
 #include "SkRasterClip.h"
 #include "SkStrikeCache.h"
 
+static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) {
+    static constexpr SkScalar kSubpixelRounding = SkFixedToScalar(SkGlyph::kSubpixelRound);
+
+    switch (axisAlignment) {
+        case kX_SkAxisAlignment:
+            return {kSubpixelRounding, SK_ScalarHalf};
+        case kY_SkAxisAlignment:
+            return {SK_ScalarHalf, kSubpixelRounding};
+        case kNone_SkAxisAlignment:
+            return {kSubpixelRounding, kSubpixelRounding};
+    }
+    SK_ABORT("Should not get here.");
+    return {0.0f, 0.0f};
+}
+
+
 // -- SkGlyphRunListPainter ------------------------------------------------------------------------
 SkGlyphRunListPainter::SkGlyphRunListPainter(
         const SkSurfaceProps& props, SkColorType colorType, SkScalerContextFlags flags)
@@ -149,7 +164,7 @@
         // Add rounding and origin.
         SkMatrix matrix = deviceMatrix;
         SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
-        SkPoint rounding = SkFindAndPlaceGlyph::SubpixelPositionRounding(axisAlignment);
+        SkPoint rounding = SubpixelPositionRounding(axisAlignment);
         matrix.preTranslate(origin.x(), origin.y());
         matrix.postTranslate(rounding.x(), rounding.y());
         matrix.mapPoints(fPositions, glyphRun.positions().data(), runSize);
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 4d9de52..c2c0fa7 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -15,8 +15,8 @@
 
 #include "SkDevice.h"
 #include "SkDraw.h"
-#include "SkFindAndPlaceGlyph.h"
 #include "SkGlyphRun.h"
+#include "SkGlyphCache.h"
 #include "SkPathEffect.h"
 #include "SkRemoteGlyphCacheImpl.h"
 #include "SkStrikeCache.h"
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index 222504c..f89abd5 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -396,7 +396,7 @@
     }
 
     bool onGetROPixels(SkBitmap* dst) const override {
-        const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->width(), this->height());
+        const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->subset());
         if (SkBitmapCache::Find(desc, dst)) {
             SkASSERT(dst->getGenerationID() == this->uniqueID());
             SkASSERT(dst->isImmutable());
@@ -417,7 +417,8 @@
             return false;
         }
 
-        if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(), 0, 0)) {
+        if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(),
+                                  this->subset().left(), this->subset().top())) {
             return false;
         }
 
diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp
index 81fa70c..94ce203 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -15,7 +15,6 @@
 #include "SkDistanceFieldGen.h"
 #include "SkDraw.h"
 #include "SkDrawProcs.h"
-#include "SkFindAndPlaceGlyph.h"
 #include "SkGlyphRun.h"
 #include "SkGr.h"
 #include "SkGraphics.h"
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index f20b64a..938ce98 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -370,6 +370,28 @@
     return nullptr;
 }
 
+sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* context,
+                                                 SkYUVColorSpace yuvColorSpace,
+                                                 const GrBackendTexture yuvaTextures[],
+                                                 const SkYUVAIndex yuvaIndices[4],
+                                                 SkISize imageSize,
+                                                 GrSurfaceOrigin imageOrigin,
+                                                 sk_sp<SkColorSpace> imageColorSpace) {
+    return nullptr;
+}
+
+sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
+        GrContext* context,
+        SkYUVColorSpace yuvColorSpace,
+        const GrBackendTexture yuvaTextures[],
+        const SkYUVAIndex yuvaIndices[4],
+        SkISize imageSize,
+        GrSurfaceOrigin imageOrigin,
+        const GrBackendTexture& backendTexture,
+        sk_sp<SkColorSpace> imageColorSpace) {
+    return nullptr;
+}
+
 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace space,
                                                 const GrBackendTexture[3],
                                                 GrSurfaceOrigin origin,
@@ -379,7 +401,7 @@
 
 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
         GrContext* context, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
-        GrSurfaceOrigin surfaceOrigin, const GrBackendTexture backendTexture,
+        GrSurfaceOrigin surfaceOrigin, const GrBackendTexture& backendTexture,
         sk_sp<SkColorSpace> colorSpace) {
     return nullptr;
 }
@@ -400,7 +422,7 @@
                                                            SkYUVColorSpace yuvColorSpace,
                                                            const GrBackendTexture nv12Textures[2],
                                                            GrSurfaceOrigin surfaceOrigin,
-                                                           const GrBackendTexture backendTexture,
+                                                           const GrBackendTexture& backendTexture,
                                                            sk_sp<SkColorSpace> colorSpace) {
     return nullptr;
 }
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 48ed8b0..b0e2232 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -283,64 +283,65 @@
                                    isBudgeted);
 }
 
-sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyImpl(GrContext* ctx,
-                                                         SkYUVColorSpace colorSpace,
-                                                         const GrBackendTexture yuvaTextures[],
-                                                         const SkYUVAIndex yuvaIndices[4],
-                                                         SkISize size,
-                                                         GrSurfaceOrigin origin,
-                                                         sk_sp<SkColorSpace> imageColorSpace) {
-    const int width = size.width();
-    const int height = size.height();
+sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
+                                                 SkYUVColorSpace yuvColorSpace,
+                                                 const GrBackendTexture yuvaTextures[],
+                                                 const SkYUVAIndex yuvaIndices[4],
+                                                 SkISize imageSize,
+                                                 GrSurfaceOrigin imageOrigin,
+                                                 sk_sp<SkColorSpace> imageColorSpace) {
+    const int width = imageSize.width();
+    const int height = imageSize.height();
 
     // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
     sk_sp<GrRenderTargetContext> renderTargetContext(
             ctx->contextPriv().makeDeferredRenderTargetContext(
                     SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig,
-                    std::move(imageColorSpace), 1, GrMipMapped::kNo, origin));
+                    std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin));
     if (!renderTargetContext) {
         return nullptr;
     }
 
-    return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, colorSpace, yuvaTextures, yuvaIndices, size,
-                                                 origin, SkBudgeted::kYes,
+    return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
+                                                 imageSize, imageOrigin, SkBudgeted::kYes,
                                                  renderTargetContext.get());
 }
 
-sk_sp<SkImage> SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
+sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
         GrContext* ctx,
-        SkYUVColorSpace colorSpace,
+        SkYUVColorSpace yuvColorSpace,
         const GrBackendTexture yuvaTextures[],
-        SkYUVAIndex yuvaIndices[4],
-        SkISize size,
-        GrSurfaceOrigin origin,
-        const GrBackendTexture backendTexture,
+        const SkYUVAIndex yuvaIndices[4],
+        SkISize imageSize,
+        GrSurfaceOrigin imageOrigin,
+        const GrBackendTexture& backendTexture,
         sk_sp<SkColorSpace> imageColorSpace) {
     GrBackendTexture backendTextureCopy = backendTexture;
 
-    if (!ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
-                                kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)) {
+    if (!SkImage_Gpu::ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
+                                             kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)) {
         return nullptr;
     }
 
     // Needs to create a render target with external texture
     // in order to draw to it for the yuv->rgb conversion.
     sk_sp<GrRenderTargetContext> renderTargetContext(
-            ctx->contextPriv().makeBackendTextureRenderTargetContext(backendTextureCopy, origin, 1,
+            ctx->contextPriv().makeBackendTextureRenderTargetContext(backendTextureCopy,
+                                                                     imageOrigin, 1,
                                                                      std::move(imageColorSpace)));
 
     if (!renderTargetContext) {
         return nullptr;
     }
 
-    return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, colorSpace, yuvaTextures, yuvaIndices, size,
-                                                 origin, SkBudgeted::kNo,
+    return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
+                                                 imageSize, imageOrigin, SkBudgeted::kNo,
                                                  renderTargetContext.get());
 }
 
-sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
+sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
                                                 const GrBackendTexture yuvTextures[3],
-                                                GrSurfaceOrigin origin,
+                                                GrSurfaceOrigin imageOrigin,
                                                 sk_sp<SkColorSpace> imageColorSpace) {
     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
     SkYUVAIndex yuvaIndices[4] = {
@@ -349,13 +350,13 @@
             SkYUVAIndex{2, SkColorChannel::kA},
             SkYUVAIndex{-1, SkColorChannel::kA}};
     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
-    return SkImage_Gpu::MakeFromYUVATexturesCopyImpl(ctx, colorSpace, yuvTextures, yuvaIndices,
-                                                     size, origin, std::move(imageColorSpace));
+    return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
+                                                 size, imageOrigin, std::move(imageColorSpace));
 }
 
 sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
-        GrContext* ctx, SkYUVColorSpace colorSpace, const GrBackendTexture yuvTextures[3],
-        GrSurfaceOrigin origin, const GrBackendTexture backendTexture,
+        GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
+        GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
         sk_sp<SkColorSpace> imageColorSpace) {
     SkYUVAIndex yuvaIndices[4] = {
             SkYUVAIndex{0, SkColorChannel::kA},
@@ -363,14 +364,14 @@
             SkYUVAIndex{2, SkColorChannel::kA},
             SkYUVAIndex{-1, SkColorChannel::kA}};
     SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
-    return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
-            ctx, colorSpace, yuvTextures, yuvaIndices, size, origin, backendTexture,
+    return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
+            ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
             std::move(imageColorSpace));
 }
 
-sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
+sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
                                                  const GrBackendTexture nv12Textures[2],
-                                                 GrSurfaceOrigin origin,
+                                                 GrSurfaceOrigin imageOrigin,
                                                  sk_sp<SkColorSpace> imageColorSpace) {
     // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
     SkYUVAIndex yuvaIndices[4] = {
@@ -379,16 +380,16 @@
             SkYUVAIndex{1, SkColorChannel::kA},
             SkYUVAIndex{-1, SkColorChannel::kA}};
     SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
-    return SkImage_Gpu::MakeFromYUVATexturesCopyImpl(ctx, colorSpace, nv12Textures, yuvaIndices,
-                                                     size, origin, std::move(imageColorSpace));
+    return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
+                                                 size, imageOrigin, std::move(imageColorSpace));
 }
 
 sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
         GrContext* ctx,
-        SkYUVColorSpace colorSpace,
+        SkYUVColorSpace yuvColorSpace,
         const GrBackendTexture nv12Textures[2],
-        GrSurfaceOrigin origin,
-        const GrBackendTexture backendTexture,
+        GrSurfaceOrigin imageOrigin,
+        const GrBackendTexture& backendTexture,
         sk_sp<SkColorSpace> imageColorSpace) {
     SkYUVAIndex yuvaIndices[4] = {
             SkYUVAIndex{0, SkColorChannel::kA},
@@ -396,8 +397,8 @@
             SkYUVAIndex{1, SkColorChannel::kA},
             SkYUVAIndex{-1, SkColorChannel::kA}};
     SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
-    return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackendImpl(
-            ctx, colorSpace, nv12Textures, yuvaIndices, size, origin, backendTexture,
+    return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
+            ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
             std::move(imageColorSpace));
 }
 
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index 9c53ae8..ec407c2 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -114,38 +114,17 @@
                                                  PromiseDoneProc promiseDoneProc,
                                                  TextureContext textureContexts[]);
 
-    /** Implementation of MakeFromYUVTexturesCopy and MakeFromNV12TexturesCopy */
-    static sk_sp<SkImage> MakeFromYUVATexturesCopyImpl(GrContext* ctx,
-                                                       SkYUVColorSpace colorSpace,
-                                                       const GrBackendTexture yuvaTextures[],
-                                                       const SkYUVAIndex yuvaIndices[4],
-                                                       SkISize size,
-                                                       GrSurfaceOrigin origin,
-                                                       sk_sp<SkColorSpace> imageColorSpace);
-
-    /** Implementation of MakeFromYUVTexturesCopyWithExternalBackend and
-        MakeFromNV12TexturesCopyWithExternalBackend */
-    static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackendImpl(
-            GrContext* ctx,
-            SkYUVColorSpace colorSpace,
-            const GrBackendTexture yuvaTextures[],
-            SkYUVAIndex yuvaIndices[4],
-            SkISize size,
-            GrSurfaceOrigin origin,
-            const GrBackendTexture backendTexture,
-            sk_sp<SkColorSpace> imageColorSpace);
-
     void resetContext(sk_sp<GrContext> newContext) {
         SkASSERT(fContext->uniqueID() == newContext->uniqueID());
         fContext = newContext;
     }
 
-private:
     static sk_sp<SkImage> ConvertYUVATexturesToRGB(
-            GrContext* ctx, SkYUVColorSpace colorSpace, const GrBackendTexture yuvaTextures[],
-            const SkYUVAIndex yuvaIndices[4], SkISize size, GrSurfaceOrigin origin,
-            SkBudgeted isBudgeted, GrRenderTargetContext* renderTargetContext);
+            GrContext*, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvaTextures[],
+            const SkYUVAIndex yuvaIndices[4], SkISize imageSize, GrSurfaceOrigin imageOrigin,
+            SkBudgeted, GrRenderTargetContext*);
 
+private:
     sk_sp<GrTextureProxy> fProxy;
 
     typedef SkImage_GpuBase INHERITED;
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index a814013..2350cb8 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -158,8 +158,8 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
 bool SkImage_Lazy::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap) const {
-    return SkBitmapCache::Find(SkBitmapCacheDesc::Make(fUniqueID,
-                                                       fInfo.width(), fInfo.height()), bitmap) &&
+    auto desc = SkBitmapCacheDesc::Make(fUniqueID, SkIRect::MakeSize(fInfo.dimensions()));
+    return SkBitmapCache::Find(desc, bitmap) &&
            check_output_bitmap(*bitmap, fUniqueID);
 }
 
@@ -210,7 +210,7 @@
     SkBitmapCache::RecPtr cacheRec;
     SkPixmap pmap;
     if (SkImage::kAllow_CachingHint == chint) {
-        auto desc = SkBitmapCacheDesc::Make(fUniqueID, info.width(), info.height());
+        auto desc = SkBitmapCacheDesc::Make(fUniqueID, SkIRect::MakeSize(info.dimensions()));
         cacheRec = SkBitmapCache::Alloc(desc, info, &pmap);
         if (!cacheRec) {
             return false;
diff --git a/tests/SpecialImageTest.cpp b/tests/SpecialImageTest.cpp
index fc09b47..06cd7bf 100644
--- a/tests/SpecialImageTest.cpp
+++ b/tests/SpecialImageTest.cpp
@@ -293,3 +293,41 @@
         test_image(subSImg2, reporter, context, true, kPad, kFullSize);
     }
 }
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_ReadbackAndCachingSubsets_Gpu, reporter, ctxInfo) {
+    GrContext* context = ctxInfo.grContext();
+    SkImageInfo ii = SkImageInfo::Make(50, 50, kN32_SkColorType, kPremul_SkAlphaType);
+    auto surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
+
+    // Fill out our surface:
+    // Green | Blue
+    //  Red  | Green
+    {
+        surface->getCanvas()->clear(SK_ColorGREEN);
+        SkPaint p;
+        p.setColor(SK_ColorRED);
+        surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 25, 25, 25), p);
+        p.setColor(SK_ColorBLUE);
+        surface->getCanvas()->drawRect(SkRect::MakeXYWH(25, 0, 25, 25), p);
+    }
+
+    auto image = surface->makeImageSnapshot();
+    auto redImg  = SkSpecialImage::MakeFromImage(SkIRect::MakeXYWH(10, 30, 10, 10), image, nullptr);
+    auto blueImg = SkSpecialImage::MakeFromImage(SkIRect::MakeXYWH(30, 10, 10, 10), image, nullptr);
+
+    // This isn't necessary, but if it ever becomes false, then the cache collision bug that we're
+    // checking below is irrelevant.
+    REPORTER_ASSERT(reporter, redImg->uniqueID() == blueImg->uniqueID());
+
+    SkBitmap redBM, blueBM;
+    SkAssertResult(redImg->getROPixels(&redBM));
+    SkAssertResult(blueImg->getROPixels(&blueBM));
+
+    // Each image should read from the correct sub-rect. Past bugs (skbug.com/8448) have included:
+    // - Always reading back from (0, 0), producing green
+    // - Incorrectly hitting the cache on the 2nd read-back, causing blueBM to be red
+    REPORTER_ASSERT(reporter, redBM.getColor(0, 0) == SK_ColorRED,
+                    "0x%08x != 0x%08x", redBM.getColor(0, 0), SK_ColorRED);
+    REPORTER_ASSERT(reporter, blueBM.getColor(0, 0) == SK_ColorBLUE,
+                    "0x%08x != 0x%08x", blueBM.getColor(0, 0), SK_ColorBLUE);
+}