Reland "implemented metal gpu backend texture upload testing"

This reverts commit a80a012456a95a6996a8901268ec34ed0cc3aecb.

Reason for revert: Fix bot failure.

Original change's description:
> Revert "implemented metal gpu backend texture upload testing"
>
> This reverts commit 36848f6b30ddaca461c98e13b9976b2c449ca547.
>
> Reason for revert: Test-Android-Clang-NVIDIA_Shield-GPU-TegraX1-arm64-Debug-All-Android_CCPR failing.
>
> Original change's description:
> > implemented metal gpu backend texture upload testing
> >
> > Bug: skia:
> > Change-Id: Ia3af58a0710f7f9792b37682a3cc45dd14282b71
> > Reviewed-on: https://skia-review.googlesource.com/140248
> > Commit-Queue: Timothy Liang <timliang@google.com>
> > Reviewed-by: Greg Daniel <egdaniel@google.com>
>
> TBR=egdaniel@google.com,ethannicholas@google.com,timliang@google.com
>
> Change-Id: Idf40fc78b82aec1efbcc64221b6d2bbf63353960
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/141182
> Reviewed-by: Timothy Liang <timliang@google.com>
> Commit-Queue: Timothy Liang <timliang@google.com>

Bug: skia:
Change-Id: Ib8c5b2e0cf9de25c11c14741a32846bcc874d712
Reviewed-on: https://skia-review.googlesource.com/141183
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Timothy Liang <timliang@google.com>
diff --git a/dm/DMGpuTestProcs.cpp b/dm/DMGpuTestProcs.cpp
index abae628..ae8c7ab 100644
--- a/dm/DMGpuTestProcs.cpp
+++ b/dm/DMGpuTestProcs.cpp
@@ -19,6 +19,9 @@
 bool IsVulkanContextType(sk_gpu_test::GrContextFactory::ContextType type) {
     return kVulkan_GrBackend == GrContextFactory::ContextTypeBackend(type);
 }
+bool IsMetalContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return kMetal_GrBackend == GrContextFactory::ContextTypeBackend(type);
+}
 bool IsRenderingGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
     return IsGLContextType(type) && GrContextFactory::IsRenderingContext(type);
 }
diff --git a/gn/tests.gni b/gn/tests.gni
index 8bba918..6b08b82 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -102,6 +102,7 @@
   "$_tests/GrShapeTest.cpp",
   "$_tests/GrSKSLPrettyPrintTest.cpp",
   "$_tests/GrSurfaceTest.cpp",
+  "$_tests/GrTestingBackendTextureUploadTest.cpp",
   "$_tests/GrTextureMipMapInvalidationTest.cpp",
   "$_tests/GrTRecorderTest.cpp",
   "$_tests/HashTest.cpp",
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index be922e5..8a68b76 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -39,6 +39,23 @@
         kSkip_SyncQueue
     };
 
+#ifdef GR_TEST_UTILS
+    GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+                                                     GrPixelConfig config, bool isRT,
+                                                     GrMipMapped) override;
+
+    bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
+
+    void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
+
+    GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType,
+                                                               GrSRGBEncoded) override;
+
+    void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
+
+    void testingOnly_flushGpuAndSync() override;
+#endif
+
     bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
                        GrSurface* src, GrSurfaceOrigin srcOrigin,
                        const SkIRect& srcRect,
@@ -135,21 +152,9 @@
     void clearStencil(GrRenderTarget* target, int clearValue) override  {}
 
 #if GR_TEST_UTILS
-    GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
-                                                     GrPixelConfig config, bool isRT,
-                                                     GrMipMapped) override {
-        return GrBackendTexture();
-    }
-    bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override { return false; }
-    void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override {}
-
-    GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType,
-                                                               GrSRGBEncoded) override {
-        return {};
-    }
-    void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override {}
-
-    void testingOnly_flushGpuAndSync() override {}
+    bool createTestingOnlyMtlTextureInfo(GrPixelConfig config, int w, int h, bool texturable,
+                                         bool renderable, GrMipMapped mipMapped,
+                                         const void* srcData, GrMtlTextureInfo* info);
 #endif
 
     sk_sp<GrMtlCaps> fMtlCaps;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 41ed23e..0295659 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -95,21 +95,6 @@
     fCaps = fMtlCaps;
 
     fCmdBuffer = [fQueue commandBuffer];
-
-    MTLTextureDescriptor* txDesc = [[MTLTextureDescriptor alloc] init];
-    txDesc.textureType = MTLTextureType3D;
-    txDesc.height = 64;
-    txDesc.width = 64;
-    txDesc.depth = 64;
-    txDesc.pixelFormat = MTLPixelFormatRGBA8Unorm;
-    txDesc.arrayLength = 1;
-    txDesc.mipmapLevelCount = 1;
-    id<MTLTexture> testTexture = [fDevice newTextureWithDescriptor:txDesc];
-    // To get ride of unused var warning
-    int width = [testTexture width];
-    SkDebugf("width: %d\n", width);
-    // Unused queue warning fix
-    SkDebugf("ptr to queue: %p\n", fQueue);
 }
 
 void GrMtlGpu::submitCommandBuffer(SyncQueue sync) {
@@ -364,6 +349,171 @@
     return GrMtlRenderTarget::MakeWrappedRenderTarget(this, surfDesc, mtlTexture);
 }
 
+#ifdef GR_TEST_UTILS
+bool GrMtlGpu::createTestingOnlyMtlTextureInfo(GrPixelConfig config, int w, int h, bool texturable,
+                                                bool renderable, GrMipMapped mipMapped,
+                                                const void* srcData, GrMtlTextureInfo* info) {
+    SkASSERT(texturable || renderable);
+    if (!texturable) {
+        SkASSERT(GrMipMapped::kNo == mipMapped);
+        SkASSERT(!srcData);
+    }
+
+    MTLPixelFormat format;
+    if (!GrPixelConfigToMTLFormat(config, &format)) {
+        return false;
+    }
+    if (texturable && !fMtlCaps->isConfigTexturable(config)) {
+        return false;
+    }
+    if (renderable && !fMtlCaps->isConfigRenderable(config)) {
+        return false;
+    }
+    // Currently we don't support uploading pixel data when mipped.
+    if (srcData && GrMipMapped::kYes == mipMapped) {
+        return false;
+    }
+    if(!check_max_blit_width(w)) {
+        return false;
+    }
+
+    bool mipmapped = mipMapped == GrMipMapped::kYes ? true : false;
+    MTLTextureDescriptor* desc =
+            [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: format
+                                                               width: w
+                                                              height: h
+                                                           mipmapped: mipmapped];
+    desc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
+    desc.storageMode = MTLStorageModePrivate;
+    desc.usage = texturable ? MTLTextureUsageShaderRead : 0;
+    desc.usage |= renderable ? MTLTextureUsageRenderTarget : 0;
+    id<MTLTexture> testTexture = [fDevice newTextureWithDescriptor: desc];
+
+    SkAutoTMalloc<GrColor> srcBuffer;
+    if (!srcData) {
+        srcBuffer.reset(w * h);
+        memset(srcBuffer, 0, w * h * sizeof(GrColor));
+        srcData = srcBuffer;
+    }
+    SkASSERT(srcData);
+
+    desc.storageMode = MTLStorageModeManaged;
+    id<MTLTexture> transferTexture = [fDevice newTextureWithDescriptor: desc];
+    auto colorType = GrPixelConfigToColorType(config);
+    int rowBytes = w * GrColorTypeBytesPerPixel(colorType);
+    MTLOrigin origin = MTLOriginMake(0, 0, 0);
+
+    SkASSERT(testTexture.pixelFormat == transferTexture.pixelFormat);
+    SkASSERT(testTexture.sampleCount == transferTexture.sampleCount);
+
+    id<MTLCommandBuffer> cmdBuffer = [fQueue commandBuffer];
+    id<MTLBlitCommandEncoder> blitCmdEncoder = [cmdBuffer blitCommandEncoder];
+    int currentWidth = w;
+    int currentHeight = h;
+    for (int mipLevel = 0; mipLevel < (int)testTexture.mipmapLevelCount; mipLevel++) {
+        [transferTexture replaceRegion: MTLRegionMake2D(0, 0, currentWidth, currentHeight)
+                           mipmapLevel: mipLevel
+                             withBytes: srcData
+                           bytesPerRow: rowBytes];
+
+        [blitCmdEncoder copyFromTexture: transferTexture
+                            sourceSlice: 0
+                            sourceLevel: mipLevel
+                           sourceOrigin: origin
+                             sourceSize: MTLSizeMake(currentWidth, currentHeight, 1)
+                              toTexture: testTexture
+                       destinationSlice: 0
+                       destinationLevel: mipLevel
+                      destinationOrigin: origin];
+        currentWidth = SkTMax(1, currentWidth/2);
+        currentHeight = SkTMax(1, currentHeight/2);
+    }
+    [blitCmdEncoder endEncoding];
+    [cmdBuffer commit];
+    [cmdBuffer waitUntilCompleted];
+
+    info->fTexture = GrReleaseId(testTexture);
+    return true;
+}
+
+GrBackendTexture GrMtlGpu::createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+                                                           GrPixelConfig config, bool isRT,
+                                                           GrMipMapped mipMapped) {
+    if (w > this->caps()->maxTextureSize() || h > this->caps()->maxTextureSize()) {
+        return GrBackendTexture();
+    }
+    GrMtlTextureInfo info;
+    if (!this->createTestingOnlyMtlTextureInfo(config, w, h, true, isRT, mipMapped, pixels,
+                                               &info)) {
+        return {};
+    }
+
+    GrBackendTexture backendTex(w, h, mipMapped, info);
+    backendTex.fConfig = config;
+    return backendTex;
+}
+
+bool GrMtlGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
+    SkASSERT(kMetal_GrBackend == tex.backend());
+
+    GrMtlTextureInfo info;
+    if (!tex.getMtlTextureInfo(&info)) {
+        return false;
+    }
+    id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture,
+                                                GrWrapOwnership::kBorrow_GrWrapOwnership);
+    if (!mtlTexture) {
+        return false;
+    }
+    return mtlTexture.usage & MTLTextureUsageShaderRead;
+}
+
+void GrMtlGpu::deleteTestingOnlyBackendTexture(const GrBackendTexture& tex) {
+    SkASSERT(kMetal_GrBackend == tex.fBackend);
+
+    GrMtlTextureInfo info;
+    if (tex.getMtlTextureInfo(&info)) {
+        // Adopts the metal texture so that ARC will clean it up.
+        GrGetMTLTexture(info.fTexture, GrWrapOwnership::kAdopt_GrWrapOwnership);
+    }
+}
+
+GrBackendRenderTarget GrMtlGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType ct,
+                                                                     GrSRGBEncoded srgbEncoded) {
+    if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
+        return GrBackendRenderTarget();
+    }
+    auto config = GrColorTypeToPixelConfig(ct, srgbEncoded);
+    if (kUnknown_GrPixelConfig == config) {
+        return {};
+    }
+    GrMtlTextureInfo info;
+    if (!this->createTestingOnlyMtlTextureInfo(config, w, h, false, true, GrMipMapped::kNo, nullptr,
+                                               &info)) {
+        return {};
+    }
+
+    GrBackendRenderTarget backendRT(w, h, 1, info);
+    backendRT.fConfig = config;
+    return backendRT;
+}
+
+void GrMtlGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
+    SkASSERT(kMetal_GrBackend == rt.fBackend);
+
+    GrMtlTextureInfo info;
+    if (rt.getMtlTextureInfo(&info)) {
+        this->testingOnly_flushGpuAndSync();
+        // Adopts the metal texture so that ARC will clean it up.
+        GrGetMTLTexture(info.fTexture, GrWrapOwnership::kAdopt_GrWrapOwnership);
+    }
+}
+
+void GrMtlGpu::testingOnly_flushGpuAndSync() {
+    this->submitCommandBuffer(kForce_SyncQueue);
+}
+#endif // GR_TEST_UTILS
+
 bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
                             GrColorType dstColorType, void* buffer, size_t rowBytes) {
     SkASSERT(surface);
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index a184bfa..b3a7829 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -35,6 +35,11 @@
 const void* GrGetPtrFromId(id idObject);
 
 /**
+ * Returns a const void* to whatever the id object is pointing to. Always uses __bridge_retained.
+ */
+const void* GrReleaseId(id idObject);
+
+/**
  * Returns a MTLTextureDescriptor which describes the MTLTexture. Useful when creating a duplicate
  * MTLTexture without the same storage allocation.
  */
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index b658920..5a58a25 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -126,6 +126,10 @@
     return (__bridge const void*)idObject;
 }
 
+const void* GrReleaseId(id idObject) {
+    return (__bridge_retained const void*)idObject;
+}
+
 MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) {
     MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
     texDesc.textureType = mtlTexture.textureType;
diff --git a/tests/GrTestingBackendTextureUploadTest.cpp b/tests/GrTestingBackendTextureUploadTest.cpp
new file mode 100644
index 0000000..e4fec18
--- /dev/null
+++ b/tests/GrTestingBackendTextureUploadTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+
+#include "GrGpu.h"
+#include "GrContextPriv.h"
+#include "GrTexture.h"
+#include "SkConvertPixels.h"
+#include "Test.h"
+#include "TestUtils.h"
+
+void testing_only_texture_test(skiatest::Reporter* reporter, GrContext* context, GrColorType ct,
+                               bool renderTarget, bool doDataUpload, GrMipMapped mipMapped) {
+    const int kWidth = 16;
+    const int kHeight = 16;
+    SkAutoTMalloc<GrColor> srcBuffer;
+    if (doDataUpload) {
+        srcBuffer.reset(kWidth * kHeight);
+        fill_pixel_data(kWidth, kHeight, srcBuffer.get());
+    }
+    SkAutoTMalloc<GrColor> dstBuffer(kWidth * kHeight);
+
+    GrGpu* gpu = context->contextPriv().getGpu();
+
+    GrPixelConfig config = GrColorTypeToPixelConfig(ct, GrSRGBEncoded::kNo);
+    if (!gpu->caps()->isConfigTexturable(config)) {
+        return;
+    }
+    if (gpu->caps()->supportedReadPixelsColorType(config, ct) != ct) {
+        return;
+    }
+
+    GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(srcBuffer,
+                                                                       kWidth,
+                                                                       kHeight,
+                                                                       config,
+                                                                       renderTarget,
+                                                                       mipMapped);
+    sk_sp<GrTexture> wrappedTex;
+    if (renderTarget) {
+        wrappedTex = gpu->wrapRenderableBackendTexture(backendTex, 1,
+                                                       GrWrapOwnership::kAdopt_GrWrapOwnership);
+    } else {
+        wrappedTex = gpu->wrapBackendTexture(backendTex,
+                                             GrWrapOwnership::kAdopt_GrWrapOwnership);
+    }
+    REPORTER_ASSERT(reporter, wrappedTex);
+
+    int rowBytes = GrColorTypeBytesPerPixel(ct) * kWidth;
+    bool result = gpu->readPixels(wrappedTex.get(), 0, 0, kWidth,
+                                  kHeight, ct, dstBuffer, rowBytes);
+
+    if (!doDataUpload) {
+        // createTestingOnlyBackendTexture will fill the texture with 0's if no data is provided, so
+        // we set the expected result likewise.
+        srcBuffer.reset(kWidth * kHeight);
+        memset(srcBuffer, 0, kWidth * kHeight * sizeof(GrColor));
+    }
+    REPORTER_ASSERT(reporter, result);
+    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(srcBuffer, dstBuffer,
+                                                                     kWidth, kHeight));
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTestingBackendTextureUploadTest, reporter, ctxInfo) {
+    for (auto colorType: {GrColorType::kRGBA_8888, GrColorType::kBGRA_8888}) {
+        for (bool renderable: {true, false}) {
+            for (bool doDataUpload: {true, false}) {
+                testing_only_texture_test(reporter, ctxInfo.grContext(), colorType,
+                                          renderable, doDataUpload, GrMipMapped::kNo);
+
+                if (!doDataUpload) {
+                    testing_only_texture_test(reporter, ctxInfo.grContext(), colorType,
+                                              renderable, doDataUpload, GrMipMapped::kYes);
+                }
+            }
+        }
+    }
+}
+
diff --git a/tests/Test.h b/tests/Test.h
index 97604a2..a4c931b 100644
--- a/tests/Test.h
+++ b/tests/Test.h
@@ -129,6 +129,7 @@
 
 extern bool IsGLContextType(GrContextFactoryContextType);
 extern bool IsVulkanContextType(GrContextFactoryContextType);
+extern bool IsMetalContextType(GrContextFactoryContextType);
 extern bool IsRenderingGLContextType(GrContextFactoryContextType);
 extern bool IsNullGLContextType(GrContextFactoryContextType);
 void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
@@ -213,6 +214,9 @@
 #define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info)                        \
         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType,                      \
                                  reporter, context_info, nullptr)
+#define DEF_GPUTEST_FOR_METAL_CONTEXT(name, reporter, context_info)                         \
+        DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsMetalContextType,                       \
+                                 reporter, context_info, nullptr)
 
 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)                          \
     do {                                                                   \
diff --git a/tests/TestUtils.cpp b/tests/TestUtils.cpp
index 44a78c5..8b611c2 100644
--- a/tests/TestUtils.cpp
+++ b/tests/TestUtils.cpp
@@ -113,3 +113,32 @@
         }
     }
 }
+
+void fill_pixel_data(int width, int height, GrColor* data) {
+    for (int j = 0; j < height; ++j) {
+        for (int i = 0; i < width; ++i) {
+            unsigned int red = (unsigned int)(256.f * (i / (float)width));
+            unsigned int green = (unsigned int)(256.f * (j / (float)height));
+            data[i + j * width] = GrColorPackRGBA(red - (red >> 8), green - (green >> 8),
+                                                  0xff, 0xff);
+        }
+    }
+}
+
+bool does_full_buffer_contain_correct_color(GrColor* srcBuffer,
+                                            GrColor* dstBuffer,
+                                            int width,
+                                            int height) {
+    GrColor* srcPtr = srcBuffer;
+    GrColor* dstPtr = dstBuffer;
+    for (int j = 0; j < height; ++j) {
+        for (int i = 0; i < width; ++i) {
+            if (srcPtr[i] != dstPtr[i]) {
+                return false;
+            }
+        }
+        srcPtr += width;
+        dstPtr += width;
+    }
+    return true;
+}
diff --git a/tests/TestUtils.h b/tests/TestUtils.h
index 1fe96bf..e891931 100644
--- a/tests/TestUtils.h
+++ b/tests/TestUtils.h
@@ -9,6 +9,7 @@
 
 class GrSurfaceContext;
 class GrSurfaceProxy;
+typedef uint32_t GrColor;
 
 // Ensure that reading back from 'srcContext' as RGBA 8888 matches 'expectedPixelValues
 void test_read_pixels(skiatest::Reporter*,
@@ -29,3 +30,10 @@
 // Ensure that RGBA 8888 pixels can be copied into 'dstContext'
 void test_copy_to_surface(skiatest::Reporter*, GrProxyProvider*,
                           GrSurfaceContext* dstContext, const char* testName);
+
+// Fills data with a red-green gradient
+void fill_pixel_data(int width, int height, GrColor* data);
+
+// Checks srcBuffer and dstBuffer contain the same colors
+bool does_full_buffer_contain_correct_color(GrColor* srcBuffer, GrColor* dstBuffer, int width,
+                                            int height);
diff --git a/tests/VkUploadPixelsTests.cpp b/tests/VkUploadPixelsTests.cpp
index bd87d19..b13de41 100644
--- a/tests/VkUploadPixelsTests.cpp
+++ b/tests/VkUploadPixelsTests.cpp
@@ -18,40 +18,11 @@
 #include "ProxyUtils.h"
 #include "SkGr.h"
 #include "Test.h"
+#include "TestUtils.h"
 #include "vk/GrVkGpu.h"
 
 using sk_gpu_test::GrContextFactory;
 
-void fill_pixel_data(int width, int height, GrColor* data) {
-
-    // build red-green gradient
-    for (int j = 0; j < height; ++j) {
-        for (int i = 0; i < width; ++i) {
-            unsigned int red = (unsigned int)(256.f*(i / (float)width));
-            unsigned int green = (unsigned int)(256.f*(j / (float)height));
-            data[i + j*width] = GrColorPackRGBA(red - (red>>8), green - (green>>8), 0xff, 0xff);
-        }
-    }
-}
-
-bool does_full_buffer_contain_correct_color(GrColor* srcBuffer,
-                                            GrColor* dstBuffer,
-                                            int width,
-                                            int height) {
-    GrColor* srcPtr = srcBuffer;
-    GrColor* dstPtr = dstBuffer;
-    for (int j = 0; j < height; ++j) {
-        for (int i = 0; i < width; ++i) {
-            if (srcPtr[i] != dstPtr[i]) {
-                return false;
-            }
-        }
-        srcPtr += width;
-        dstPtr += width;
-    }
-    return true;
-}
-
 void basic_texture_test(skiatest::Reporter* reporter, GrContext* context, SkColorType ct,
                         bool renderTarget) {
     const int kWidth = 16;