Use GrSurfaceContext::read/write-Pixels more

Change-Id: I04bcaf91aa7a43e0563e332c1fe2836d762a04d4
Reviewed-on: https://skia-review.googlesource.com/7520
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index aab1050..b3f15be 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -343,9 +343,12 @@
     }
 
     GrSurfaceProxy* asDeferredSurface() override { return fRenderTargetProxy.get(); }
+    const GrSurfaceProxy* asDeferredSurface() const override { return fRenderTargetProxy.get(); }
     GrTextureProxy* asDeferredTexture() override;
     GrRenderTargetProxy* asDeferredRenderTarget() override { return fRenderTargetProxy.get(); }
 
+    GrRenderTargetContext* asRenderTargetContext() override { return this; }
+
     sk_sp<GrTexture> asTexture() {
         if (!this->accessRenderTarget()) {
             return nullptr;
diff --git a/include/gpu/GrSurfaceContext.h b/include/gpu/GrSurfaceContext.h
index 6a40f2f..75ee952 100644
--- a/include/gpu/GrSurfaceContext.h
+++ b/include/gpu/GrSurfaceContext.h
@@ -14,6 +14,7 @@
 
 class GrAuditTrail;
 class GrContext;
+class GrRenderTargetContext;
 class GrRenderTargetProxy;
 class GrSingleOwner;
 class GrSurface;
@@ -34,6 +35,10 @@
     sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
     bool isGammaCorrect() const { return SkToBool(fColorSpace.get()); }
 
+    // TODO: these two calls would be way cooler if this object had a GrSurfaceProxy pointer
+    int width() const { return this->asDeferredSurface()->width(); }
+    int height() const { return this->asDeferredSurface()->height(); }
+
     /*
      * Copy 'src' into the proxy backing this context
      * @param src       src of pixels
@@ -91,9 +96,12 @@
 
     // TODO: this is virtual b.c. this object doesn't have a pointer to the wrapped GrSurfaceProxy?
     virtual GrSurfaceProxy* asDeferredSurface() = 0;
+    virtual const GrSurfaceProxy* asDeferredSurface() const = 0;
     virtual GrTextureProxy* asDeferredTexture() = 0;
     virtual GrRenderTargetProxy* asDeferredRenderTarget() = 0;
 
+    virtual GrRenderTargetContext* asRenderTargetContext() { return nullptr; }
+
     GrAuditTrail* auditTrail() { return fAuditTrail; }
 
     // Provides access to functions that aren't part of the public API.
diff --git a/include/gpu/GrTextureContext.h b/include/gpu/GrTextureContext.h
index b49b272..79a1719 100644
--- a/include/gpu/GrTextureContext.h
+++ b/include/gpu/GrTextureContext.h
@@ -28,6 +28,7 @@
     ~GrTextureContext() override;
 
     GrSurfaceProxy* asDeferredSurface() override { return fTextureProxy.get(); }
+    const GrSurfaceProxy* asDeferredSurface() const override { return fTextureProxy.get(); }
     GrTextureProxy* asDeferredTexture() override { return fTextureProxy.get(); }
     GrRenderTargetProxy* asDeferredRenderTarget() override;
 
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 12972c2..9363b82 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -16,6 +16,7 @@
 class GrCaps;
 class GrRenderTargetOpList;
 class GrRenderTargetProxy;
+class GrSurfaceContext;
 class GrTextureOpList;
 class GrTextureProvider;
 class GrTextureProxy;
@@ -277,8 +278,8 @@
     }
 
     // Test-only entry point - should decrease in use as proxies propagate
-    static sk_sp<GrSurfaceProxy> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
-                                          GrTexture* srcTexture, SkBudgeted budgeted);
+    static sk_sp<GrSurfaceContext> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
+                                            GrSurfaceProxy* srcProxy);
 
     bool isWrapped_ForTesting() const;
 
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 3315c94..ed9691c 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -35,6 +35,12 @@
                                                        SkBackingFit dstFit,
                                                        SkBudgeted isDstBudgeted);
 
+    // TODO: add:
+    // sk_sp<GrSurfaceContext> makeBackendSurfaceContext(const GrBackendTextureDesc& desc,
+    //                                                   sk_sp<SkColorSpace> colorSpace,
+    //                                                   GrWrapOwnership = kBorrow_GrWrapOwnership);
+    // Maybe add a 'surfaceProps' param that is ignored for non-RTs?
+
     sk_sp<GrRenderTargetContext> makeBackendTextureRenderTargetContext(
                                                          const GrBackendTextureDesc& desc,
                                                          sk_sp<SkColorSpace> colorSpace,
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 48fc401..4cf4611 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -196,25 +196,20 @@
     return sk_ref_sp(dstContext->asDeferredSurface());
 }
 
-sk_sp<GrSurfaceProxy> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
-                                               GrTexture* srcTexture, SkBudgeted budgeted) {
+sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
+                                                 GrSurfaceProxy* srcProxy) {
 
     sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
                                                                             dstDesc,
                                                                             SkBackingFit::kExact,
-                                                                            budgeted));
+                                                                            SkBudgeted::kYes));
     if (!dstContext) {
         return nullptr;
     }
 
-    sk_sp<GrSurfaceProxy> srcProxy(GrSurfaceProxy::MakeWrapped(sk_ref_sp(srcTexture)));
-    if (!srcProxy) {
+    if (!dstContext->copy(srcProxy)) {
         return nullptr;
     }
 
-    if (!dstContext->copy(srcProxy.get())) {
-        return nullptr;
-    }
-
-    return sk_ref_sp(dstContext->asDeferredSurface());
+    return dstContext;
 }
diff --git a/tests/CopySurfaceTest.cpp b/tests/CopySurfaceTest.cpp
index efb6b2d..19037d9 100644
--- a/tests/CopySurfaceTest.cpp
+++ b/tests/CopySurfaceTest.cpp
@@ -56,6 +56,8 @@
         {-1   , -1   },
     };
 
+    const SkImageInfo ii = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+
     SkAutoTMalloc<uint32_t> read(kW * kH);
 
     for (auto sOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
@@ -90,10 +92,11 @@
                                 continue;
                             }
 
-                            sk_sp<GrSurfaceContext> sContext =
-                                   context->contextPriv().makeWrappedSurfaceContext(dst, nullptr);
+                            sk_sp<GrSurfaceContext> dstContext =
+                                   context->contextPriv().makeWrappedSurfaceContext(std::move(dst),
+                                                                                    nullptr);
 
-                            bool result = sContext->copy(src.get(), srcRect, dstPoint);
+                            bool result = dstContext->copy(src.get(), srcRect, dstPoint);
 
                             bool expectedResult = true;
                             SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
@@ -130,11 +133,8 @@
                                 continue;
                             }
 
-                            GrSurface* dstSurf = dst->instantiate(context->textureProvider());
-
                             sk_memset32(read.get(), 0, kW * kH);
-                            if (!dstSurf->readPixels(0, 0, kW, kH, baseDesc.fConfig, read.get(),
-                                                     kRowBytes)) {
+                            if (!dstContext->readPixels(ii, read.get(), kRowBytes, 0, 0)) {
                                 ERRORF(reporter, "Error calling readPixels");
                                 continue;
                             }
diff --git a/tests/EGLImageTest.cpp b/tests/EGLImageTest.cpp
index 0dcacf9..79d3261 100644
--- a/tests/EGLImageTest.cpp
+++ b/tests/EGLImageTest.cpp
@@ -8,6 +8,7 @@
 #include "Test.h"
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrContextFactory.h"
 #include "GrShaderCaps.h"
 #include "GrSurfaceContext.h"
@@ -41,13 +42,16 @@
 }
 
 static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
-                             GrSurface* externalTexture, uint32_t expectedPixelValues[]) {
-    int pixelCnt = externalTexture->width() * externalTexture->height();
+                             GrSurfaceContext* externalTextureContext,
+                             uint32_t expectedPixelValues[]) {
+    int pixelCnt = externalTextureContext->width() * externalTextureContext->height();
     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
     memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
-    bool read = externalTexture->readPixels(0, 0, externalTexture->width(),
-                                            externalTexture->height(), kRGBA_8888_GrPixelConfig,
-                                            pixels.get());
+
+    SkImageInfo ii = SkImageInfo::Make(externalTextureContext->width(), 
+                                       externalTextureContext->height(),
+                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+    bool read = externalTextureContext->readPixels(ii, pixels.get(), 0, 0, 0);
     if (!read) {
         ERRORF(reporter, "Error reading external texture.");
     }
@@ -61,29 +65,32 @@
 }
 
 static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
-                              GrTexture* externalTexture) {
-    int pixelCnt = externalTexture->width() * externalTexture->height();
+                              GrSurfaceContext* externalTextureContext) {
+    int pixelCnt = externalTextureContext->width() * externalTextureContext->height();
     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
     memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
-    bool write = externalTexture->writePixels(0, 0, 0, 0, kRGBA_8888_GrPixelConfig, pixels.get());
+
+    SkImageInfo ii = SkImageInfo::Make(externalTextureContext->width(),
+                                       externalTextureContext->height(),
+                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+    bool write = externalTextureContext->writePixels(ii, pixels.get(), 0, 0, 0);
     REPORTER_ASSERT_MESSAGE(reporter, !write, "Should not be able to write to a EXTERNAL"
                                               " texture.");
 }
 
 static void test_copy_surface(skiatest::Reporter* reporter, GrContext* context,
-                              GrTexture* externalTexture, uint32_t expectedPixelValues[]) {
+                              GrSurfaceProxy* externalTextureProxy,
+                              uint32_t expectedPixelValues[]) {
     GrSurfaceDesc copyDesc;
     copyDesc.fConfig = kRGBA_8888_GrPixelConfig;
-    copyDesc.fWidth = externalTexture->width();
-    copyDesc.fHeight = externalTexture->height();
+    copyDesc.fWidth = externalTextureProxy->width();
+    copyDesc.fHeight = externalTextureProxy->height();
     copyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
 
-    sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, copyDesc,
-                                                        externalTexture, SkBudgeted::kYes));
+    sk_sp<GrSurfaceContext> copyContext(GrSurfaceProxy::TestCopy(context, copyDesc,
+                                                                 externalTextureProxy));
 
-    GrSurface* copySurf = copy->instantiate(context->textureProvider());
-
-    test_read_pixels(reporter, context, copySurf, expectedPixelValues);
+    test_read_pixels(reporter, context, copyContext.get(), expectedPixelValues);
 }
 
 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) {
@@ -178,37 +185,50 @@
     externalDesc.fWidth = kSize;
     externalDesc.fHeight = kSize;
     externalDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
-    sk_sp<GrTexture> externalTextureObj(
-        context0->textureProvider()->wrapBackendTexture(externalDesc));
-    if (!externalTextureObj) {
-        ERRORF(reporter, "Error wrapping external texture in GrTexture.");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image);
-        return;
+
+    sk_sp<GrSurfaceContext> externalTextureContext;
+
+    {
+        sk_sp<GrTexture> externalTextureObj(
+            context0->textureProvider()->wrapBackendTexture(externalDesc));
+        if (!externalTextureObj) {
+            ERRORF(reporter, "Error wrapping external texture in GrTexture.");
+            cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image);
+            return;
+        }
+
+        externalTextureContext = context0->contextPriv().makeWrappedSurfaceContext(
+                                                                    std::move(externalTextureObj));
     }
 
     // Should not be able to wrap as a RT
-    externalDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
-    sk_sp<GrTexture> externalTextureRTObj(
-        context0->textureProvider()->wrapBackendTexture(externalDesc));
-    if (externalTextureRTObj) {
-        ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT.");
+    {
+        externalDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
+        sk_sp<GrTexture> externalTextureRTObj(
+            context0->textureProvider()->wrapBackendTexture(externalDesc));
+        if (externalTextureRTObj) {
+            ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT.");
+        }
+        externalDesc.fFlags = kNone_GrBackendTextureFlag;
     }
-    externalDesc.fFlags = kNone_GrBackendTextureFlag;
 
     // Should not be able to wrap with a sample count
-    externalDesc.fSampleCnt = 4;
-    sk_sp<GrTexture> externalTextureMSAAObj(
-        context0->textureProvider()->wrapBackendTexture(externalDesc));
-    if (externalTextureMSAAObj) {
-        ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture with MSAA.");
+    {
+        externalDesc.fSampleCnt = 4;
+        sk_sp<GrTexture> externalTextureMSAAObj(
+            context0->textureProvider()->wrapBackendTexture(externalDesc));
+        if (externalTextureMSAAObj) {
+            ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture with MSAA.");
+        }
+        externalDesc.fSampleCnt = 0;
     }
-    externalDesc.fSampleCnt = 0;
 
-    test_read_pixels(reporter, context0, externalTextureObj.get(), pixels.get());
+    test_read_pixels(reporter, context0, externalTextureContext.get(), pixels.get());
 
-    test_write_pixels(reporter, context0, externalTextureObj.get());
+    test_write_pixels(reporter, context0, externalTextureContext.get());
 
-    test_copy_surface(reporter, context0, externalTextureObj.get(), pixels.get());
+    test_copy_surface(reporter, context0, externalTextureContext->asDeferredSurface(),
+                      pixels.get());
 
     cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, backendTexture1, image);
 }
diff --git a/tests/FloatingPointTextureTest.cpp b/tests/FloatingPointTextureTest.cpp
index 8f0be39..95917b4 100644
--- a/tests/FloatingPointTextureTest.cpp
+++ b/tests/FloatingPointTextureTest.cpp
@@ -43,8 +43,7 @@
         desc.fWidth = DEV_W;
         desc.fHeight = DEV_H;
         desc.fConfig = config;
-        desc.fOrigin = 0 == origin ?
-            kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
+        desc.fOrigin = 0 == origin ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
         sk_sp<GrTexture> fpTexture(context->textureProvider()->createTexture(
             desc, SkBudgeted::kNo, controlPixelData.begin(), 0));
         // Floating point textures are NOT supported everywhere
diff --git a/tests/GrTextureStripAtlasTest.cpp b/tests/GrTextureStripAtlasTest.cpp
index 2def782..5b1a14e 100644
--- a/tests/GrTextureStripAtlasTest.cpp
+++ b/tests/GrTextureStripAtlasTest.cpp
@@ -34,7 +34,7 @@
     }
 
     // Add a pending read to the src texture, and then make it available for reuse.
-    sk_sp<GrSurfaceProxy> targetProxy;
+    sk_sp<GrSurfaceContext> dstContext;
     GrSurface* srcSurface;
 
     {
@@ -42,18 +42,15 @@
         targetDesc.fFlags = kRenderTarget_GrSurfaceFlag;
 
         // We can't use GrSurfaceProxy::Copy bc we may be changing the dst proxy type
-        sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
-                                                                            targetDesc,
-                                                                            SkBackingFit::kExact,
-                                                                            SkBudgeted::kYes));
+        dstContext = context->contextPriv().makeDeferredSurfaceContext(targetDesc,
+                                                                       SkBackingFit::kExact,
+                                                                       SkBudgeted::kYes);
         REPORTER_ASSERT(reporter, dstContext);
 
         if (!dstContext->copy(srcProxy.get())) {
             return;
         }
 
-        targetProxy = sk_ref_sp(dstContext->asDeferredSurface());
-
         srcSurface = srcProxy->instantiate(context->textureProvider());
         srcProxy.reset();
     }
@@ -87,11 +84,9 @@
     {
         SkAutoTMalloc<uint8_t> actualPixels(sizeof(uint32_t) * desc.fWidth * desc.fHeight);
 
-        // TODO: move readPixels to GrSurfaceProxy?
-        GrSurface* surf = targetProxy->instantiate(context->textureProvider());
-
-        bool success = surf->readPixels(0, 0, desc.fWidth, desc.fHeight,
-                                        kRGBA_8888_GrPixelConfig, actualPixels.get());
+        SkImageInfo ii = SkImageInfo::Make(desc.fWidth, desc.fHeight,
+                                           kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+        bool success = dstContext->readPixels(ii, actualPixels.get(), 0, 0, 0);
         REPORTER_ASSERT(reporter, success);
 
         bool good = true;
diff --git a/tests/IntTextureTest.cpp b/tests/IntTextureTest.cpp
index 3edd4cc..23ccb50 100644
--- a/tests/IntTextureTest.cpp
+++ b/tests/IntTextureTest.cpp
@@ -36,11 +36,12 @@
         return;
     }
     static const int kS = UINT8_MAX + 1;
+    static const size_t kRowBytes = kS * sizeof(int32_t);
+
     GrSurfaceDesc desc;
     desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
     desc.fWidth = kS;
     desc.fHeight = kS;
-    sk_sp<GrTexture> texture;
 
     std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
     for (int j = 0; j < kS; ++j) {
@@ -53,66 +54,86 @@
         }
     }
 
-    // Test that attempting to create a integer texture with multiple MIP level fails.
-    GrMipLevel levels[2];
-    levels[0].fPixels = testData.get();
-    levels[0].fRowBytes = kS * sizeof(int32_t);
-    levels[1].fPixels = testData.get();
-    levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
-    texture.reset(context->textureProvider()->createMipMappedTexture(desc, SkBudgeted::kYes, levels,
-                                                                     2));
-    REPORTER_ASSERT(reporter, !texture);
+    // Test that attempting to create a integer texture with multiple MIP levels fails.
+    {
+        GrMipLevel levels[2];
+        levels[0].fPixels = testData.get();
+        levels[0].fRowBytes = kRowBytes;
+        levels[1].fPixels = testData.get();
+        levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
 
-    // Test that we can create a integer texture.
-    texture.reset(context->textureProvider()->createTexture(desc, SkBudgeted::kYes,
-                                                            levels[0].fPixels,
-                                                            levels[0].fRowBytes));
+        sk_sp<GrTexture> temp(context->textureProvider()->createMipMappedTexture(desc,
+                                                                                 SkBudgeted::kYes,
+                                                                                 levels, 2));
+        REPORTER_ASSERT(reporter, !temp);
+    }
+
+    // Test that we can create an integer texture.
+    sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*context->caps(),
+                                                                context->textureProvider(),
+                                                                desc, SkBudgeted::kYes,
+                                                                testData.get(),
+                                                                kRowBytes);
+    REPORTER_ASSERT(reporter, proxy);
+    if (!proxy || !proxy->asTextureProxy()) {
+        return;
+    }
+
+    GrTexture* texture = proxy->asTextureProxy()->instantiate(context->textureProvider());
     REPORTER_ASSERT(reporter, texture);
     if (!texture) {
         return;
     }
 
-    // Test that reading to a non-integer config fails.
     std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
-    bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_GrPixelConfig, readData.get());
-    REPORTER_ASSERT(reporter, !success);
-    std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
-    success = texture->readPixels(0, 0, kS, kS, kRGBA_half_GrPixelConfig, halfData.get());
-    REPORTER_ASSERT(reporter, !success);
-
-    // Can read back as ints. (ES only requires being able to read back into 32bit ints which
-    // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
-    // implementation-dependent second format).
-    sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
-    success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
-    REPORTER_ASSERT(reporter, success);
-    if (success) {
-        check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
+    // Test that reading to a non-integer config fails.
+    {
+        bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_GrPixelConfig, readData.get());
+        REPORTER_ASSERT(reporter, !success);
     }
-
-    // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
-    success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get(), 0,
-                                  GrContext::kUnpremul_PixelOpsFlag);
-    REPORTER_ASSERT(reporter, !success);
+    {
+        std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
+        bool success = texture->readPixels(0, 0, kS, kS, kRGBA_half_GrPixelConfig, halfData.get());
+        REPORTER_ASSERT(reporter, !success);
+    }
+    {
+        // Can read back as ints. (ES only requires being able to read back into 32bit ints which
+        // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
+        // implementation-dependent second format).
+        sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
+        bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
+                                           readData.get());
+        REPORTER_ASSERT(reporter, success);
+        if (success) {
+            check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
+        }
+    }
+    {
+        // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
+        bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
+                                           readData.get(), 0, GrContext::kUnpremul_PixelOpsFlag);
+        REPORTER_ASSERT(reporter, !success);
+    }
 
     // Test that copying from one integer texture to another succeeds.
     {
-        sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, desc,
-                                                            texture.get(), SkBudgeted::kYes));
-        REPORTER_ASSERT(reporter, copy);
-        if (!copy) {
+        sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
+                                                                    proxy.get()));
+        REPORTER_ASSERT(reporter, dstContext);
+        if (!dstContext || !dstContext->asDeferredTexture()) {
             return;
         }
 
-        GrSurface* copySurface = copy->instantiate(context->textureProvider());
+        GrSurface* copySurface = dstContext->asDeferredTexture()->instantiate(
+                                                                    context->textureProvider());
         REPORTER_ASSERT(reporter, copySurface);
         if (!copySurface) {
             return;
         }
 
         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
-        success = copySurface->readPixels(0, 0, kS, kS,
-                                          kRGBA_8888_sint_GrPixelConfig, readData.get());
+        bool success = copySurface->readPixels(0, 0, kS, kS,
+                                               kRGBA_8888_sint_GrPixelConfig, readData.get());
         REPORTER_ASSERT(reporter, success);
         if (success) {
             check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
@@ -125,9 +146,9 @@
         GrSurfaceDesc nonIntDesc = desc;
         nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
 
-        sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
-                                                            texture.get(), SkBudgeted::kYes));
-        REPORTER_ASSERT(reporter, !copy);
+        sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
+                                                                    proxy.get()));
+        REPORTER_ASSERT(reporter, !dstContext);
     }
 
     // Test that copying to a non-integer (RGBA_half) texture fails.
@@ -135,49 +156,53 @@
         GrSurfaceDesc nonIntDesc = desc;
         nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
 
-        sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
-                                                            texture.get(), SkBudgeted::kYes));
-        REPORTER_ASSERT(reporter, !copy);
+        sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
+                                                                    proxy.get()));
+        REPORTER_ASSERT(reporter, !dstContext);
     }
 
     // We overwrite the top left quarter of the texture with the bottom right quarter of the
     // original data.
     const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
-    size_t rowBytes = kS * sizeof(int32_t);
 
-    // Can't write pixels from a non-int config.
-    success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_GrPixelConfig, bottomRightQuarter,
-                                   rowBytes);
-    REPORTER_ASSERT(reporter, !success);
+    {
+        // Can't write pixels from a non-int config.
+        bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_GrPixelConfig,
+                                            bottomRightQuarter, kRowBytes);
+        REPORTER_ASSERT(reporter, !success);
+    }
+    {
+        // Can't use unpremul flag.
+        bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
+                                            bottomRightQuarter, kRowBytes,
+                                            GrContext::kUnpremul_PixelOpsFlag);
+        REPORTER_ASSERT(reporter, !success);
+    }
+    {
+        bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
+                                            bottomRightQuarter, kRowBytes);
+        REPORTER_ASSERT(reporter, success);
+        if (!success) {
+            return;
+        }
 
-    // Can't use unpremul flag.
-    success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
-                                   bottomRightQuarter, rowBytes,
-                                   GrContext::kUnpremul_PixelOpsFlag);
-    REPORTER_ASSERT(reporter, !success);
-
-    success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
-                                   bottomRightQuarter, rowBytes);
-    REPORTER_ASSERT(reporter, success);
-    if (!success) {
-        return;
+        sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
+        success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
+        REPORTER_ASSERT(reporter, success);
+        if (!success) {
+            return;
+        }
+        std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
+        memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
+        char* dst = (char*)overwrittenTestData.get();
+        char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
+        for (int i = 0; i < kS/2; ++i) {
+            memcpy(dst, src, sizeof(int32_t) * kS/2);
+            dst += kRowBytes;
+            src += kRowBytes;
+        }
+        check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
     }
-    sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
-    success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
-    REPORTER_ASSERT(reporter, success);
-    if (!success) {
-        return;
-    }
-    std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
-    memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
-    char* dst = (char*)overwrittenTestData.get();
-    char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
-    for (int i = 0; i < kS/2; ++i) {
-        memcpy(dst, src, sizeof(int32_t) * kS/2);
-        dst += rowBytes;
-        src += rowBytes;
-    }
-    check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
 
     // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
     // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
@@ -194,6 +219,7 @@
                                 ((0xFF * g) << 8) | (0xFF * r);
     }
     texture->writePixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, testData.get());
+
     sk_sp<GrRenderTargetContext> rtContext = context->makeRenderTargetContext(
             SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
 
@@ -207,7 +233,7 @@
     };
 
     for (auto filter : kNamedFilters) {
-        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(), nullptr,
+        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture, nullptr,
                                                                   SkMatrix::I(),
                                                                   filter.fMode));
         REPORTER_ASSERT(reporter, fp);
@@ -225,11 +251,14 @@
         check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
     }
 
-    // No rendering to integer textures.
-    GrSurfaceDesc intRTDesc = desc;
-    intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
-    texture.reset(context->textureProvider()->createTexture(intRTDesc, SkBudgeted::kYes));
-    REPORTER_ASSERT(reporter, !texture);
+    {
+        // No rendering to integer textures.
+        GrSurfaceDesc intRTDesc = desc;
+        intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+        sk_sp<GrTexture> temp(context->textureProvider()->createTexture(intRTDesc,
+                                                                        SkBudgeted::kYes));
+        REPORTER_ASSERT(reporter, !temp);
+    }
 }
 
 #endif
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
index 6d075df..523c2e3 100644
--- a/tests/RectangleTextureTest.cpp
+++ b/tests/RectangleTextureTest.cpp
@@ -15,15 +15,18 @@
 #include "gl/GLTestContext.h"
 
 static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
-                             GrSurface* texture, uint32_t expectedPixelValues[]) {
-    int pixelCnt = texture->width() * texture->height();
+                             GrSurfaceContext* srcContext, uint32_t expectedPixelValues[]) {
+    int pixelCnt = srcContext->width() * srcContext->height();
     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
     memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
-    bool read = texture->readPixels(0, 0, texture->width(), texture->height(),
-                                    kRGBA_8888_GrPixelConfig, pixels.get());
+
+    SkImageInfo ii = SkImageInfo::Make(srcContext->width(), srcContext->height(),
+                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+    bool read = srcContext->readPixels(ii, pixels.get(), 0, 0, 0);
     if (!read) {
         ERRORF(reporter, "Error reading rectangle texture.");
     }
+
     for (int i = 0; i < pixelCnt; ++i) {
         if (pixels.get()[i] != expectedPixelValues[i]) {
             ERRORF(reporter, "Error, pixel value %d should be 0x%08x, got 0x%08x.", i,
@@ -34,110 +37,102 @@
 }
 
 static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
-                              GrTexture* rectangleTexture) {
-    int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
+                              GrSurfaceContext* rectSurfaceContext) {
+    int pixelCnt = rectSurfaceContext->width() * rectSurfaceContext->height();
     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
-    for (int y = 0; y < rectangleTexture->width(); ++y) {
-        for (int x = 0; x < rectangleTexture->height(); ++x) {
-            pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(x, y, x + y, x * y);
+    for (int y = 0; y < rectSurfaceContext->width(); ++y) {
+        for (int x = 0; x < rectSurfaceContext->height(); ++x) {
+            pixels.get()[y * rectSurfaceContext->width() + x] = GrColorPackRGBA(x, y, x + y, x * y);
         }
     }
-    bool write = rectangleTexture->writePixels(0, 0, rectangleTexture->width(),
-                                               rectangleTexture->height(), kRGBA_8888_GrPixelConfig,
-                                               pixels.get());
+
+    SkImageInfo ii = SkImageInfo::Make(rectSurfaceContext->width(), rectSurfaceContext->height(),
+                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+    bool write = rectSurfaceContext->writePixels(ii, pixels.get(), 0, 0, 0);
     if (!write) {
         ERRORF(reporter, "Error writing to rectangle texture.");
     }
-    test_read_pixels(reporter, context, rectangleTexture, pixels.get());
+
+    test_read_pixels(reporter, context, rectSurfaceContext, pixels.get());
 }
 
 static void test_copy_surface_src(skiatest::Reporter* reporter, GrContext* context,
-                                  GrTexture* rectTexture, uint32_t expectedPixelValues[]) {
+                                  GrSurfaceProxy* rectProxy, uint32_t expectedPixelValues[]) {
     GrSurfaceDesc copyDstDesc;
     copyDstDesc.fConfig = kRGBA_8888_GrPixelConfig;
-    copyDstDesc.fWidth = rectTexture->width();
-    copyDstDesc.fHeight = rectTexture->height();
+    copyDstDesc.fWidth = rectProxy->width();
+    copyDstDesc.fHeight = rectProxy->height();
 
     for (auto flags : {kNone_GrSurfaceFlags, kRenderTarget_GrSurfaceFlag}) {
         copyDstDesc.fFlags = flags;
 
-        sk_sp<GrSurfaceProxy> dst(GrSurfaceProxy::TestCopy(context, copyDstDesc,
-                                                           rectTexture, SkBudgeted::kYes));
+        sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, copyDstDesc,
+                                                                    rectProxy));
 
-        GrSurface* dstSurf = dst->instantiate(context->textureProvider());
-
-        test_read_pixels(reporter, context, dstSurf, expectedPixelValues);
+        test_read_pixels(reporter, context, dstContext.get(), expectedPixelValues);
     }
 }
 
 static void test_copy_surface_dst(skiatest::Reporter* reporter, GrContext* context,
-                                  GrTexture* rectangleTexture) {
+                                  GrSurfaceContext* rectContext) {
 
-    sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
-                                                                    sk_ref_sp(rectangleTexture)));
-
-    int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
+    int pixelCnt = rectContext->width() * rectContext->height();
     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
-    for (int y = 0; y < rectangleTexture->width(); ++y) {
-        for (int x = 0; x < rectangleTexture->height(); ++x) {
-            pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(y, x, x * y, x *+ y);
+    for (int y = 0; y < rectContext->width(); ++y) {
+        for (int x = 0; x < rectContext->height(); ++x) {
+            pixels.get()[y * rectContext->width() + x] = GrColorPackRGBA(y, x, x * y, x *+ y);
         }
     }
     for (auto flags : {kNone_GrSurfaceFlags, kRenderTarget_GrSurfaceFlag}) {
         GrSurfaceDesc copySrcDesc;
         copySrcDesc.fConfig = kRGBA_8888_GrPixelConfig;
-        copySrcDesc.fWidth = rectangleTexture->width();
-        copySrcDesc.fHeight = rectangleTexture->height();
+        copySrcDesc.fWidth = rectContext->width();
+        copySrcDesc.fHeight = rectContext->height();
         copySrcDesc.fFlags = flags;
 
         sk_sp<GrSurfaceProxy> src(GrSurfaceProxy::MakeDeferred(*context->caps(),
                                                                context->textureProvider(),
                                                                copySrcDesc,
                                                                SkBudgeted::kYes, pixels.get(), 0));
-        sContext->copy(src.get());
+        rectContext->copy(src.get());
 
-        test_read_pixels(reporter, context, rectangleTexture, pixels.get());
+        test_read_pixels(reporter, context, rectContext, pixels.get());
     }
 }
 
 // skbug.com/5932
-static void test_basic_draw(skiatest::Reporter* reporter, GrContext* context,
-                            GrTexture* rectangleTexture, uint32_t expectedPixelValues[]) {
+static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrContext* context,
+                                   sk_sp<GrSurfaceProxy> rectProxy, uint32_t expectedPixelValues[]) {
     sk_sp<GrRenderTargetContext> rtContext(
-            context->makeRenderTargetContext(SkBackingFit::kExact, rectangleTexture->width(),
-                                             rectangleTexture->height(), rectangleTexture->config(),
+            context->makeRenderTargetContext(SkBackingFit::kExact, rectProxy->width(),
+                                             rectProxy->height(), rectProxy->config(),
                                              nullptr));
     for (auto filter : {GrSamplerParams::kNone_FilterMode,
                         GrSamplerParams::kBilerp_FilterMode,
                         GrSamplerParams::kMipMap_FilterMode}) {
         rtContext->clear(nullptr, 0xDDCCBBAA, true);
-        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(rectangleTexture, nullptr,
-                                                                  SkMatrix::I(), filter));
+        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(
+                                                        context,
+                                                        sk_ref_sp(rectProxy->asTextureProxy()),
+                                                        nullptr,
+                                                        SkMatrix::I(), filter));
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
         rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
-        test_read_pixels(reporter, context, rtContext->asTexture().get(), expectedPixelValues);
+        test_read_pixels(reporter, context, rtContext.get(), expectedPixelValues);
     }
 }
 
 static void test_clear(skiatest::Reporter* reporter, GrContext* context,
-                       GrTexture* rectangleTexture) {
-    if (rectangleTexture->asRenderTarget()) {
-        sk_sp<GrRenderTargetContext> rtc(context->contextPriv().makeWrappedRenderTargetContext(
-                                                    sk_ref_sp(rectangleTexture->asRenderTarget()),
-                                                    nullptr));
-        if (!rtc) {
-            ERRORF(reporter, "Could not get GrRenderTargetContext for rectangle texture.");
-            return;
-        }
-
+                       GrSurfaceContext* rectContext) {
+    if (GrRenderTargetContext* rtc = rectContext->asRenderTargetContext()) {
         // Clear the whole thing.
         GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD);
         rtc->clear(nullptr, color0, false);
 
-        int w = rectangleTexture->width();
-        int h = rectangleTexture->height();
+        int w = rtc->width();
+        int h = rtc->height();
         int pixelCnt = w * h;
         SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt);
 
@@ -148,7 +143,7 @@
         expectedBytes0[1] = GrColorUnpackG(color0);
         expectedBytes0[2] = GrColorUnpackB(color0);
         expectedBytes0[3] = GrColorUnpackA(color0);
-        for (int i = 0; i < rectangleTexture->width() * rectangleTexture->height(); ++i) {
+        for (int i = 0; i < rtc->width() * rtc->height(); ++i) {
             expectedPixels.get()[i] = expectedColor0;
         }
 
@@ -170,7 +165,7 @@
             }
         }
 
-        test_read_pixels(reporter, context, rectangleTexture, expectedPixels.get());
+        test_read_pixels(reporter, context, rtc, expectedPixels.get());
     }
 }
 
@@ -221,25 +216,40 @@
             }
         }
 
-        sk_sp<GrTexture> rectangleTexture(
-            context->textureProvider()->wrapBackendTexture(rectangleDesc));
-        if (!rectangleTexture) {
-            ERRORF(reporter, "Error wrapping rectangle texture in GrTexture.");
-            GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
-            continue;
+        sk_sp<GrSurfaceProxy> rectProxy;
+
+        {
+            sk_sp<GrTexture> rectangleTexture(
+                context->textureProvider()->wrapBackendTexture(rectangleDesc));
+            if (!rectangleTexture) {
+                ERRORF(reporter, "Error wrapping rectangle texture in GrTexture.");
+                GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
+                continue;
+            }
+
+            rectProxy = GrSurfaceProxy::MakeWrapped(std::move(rectangleTexture));
+            if (!rectProxy) {
+                ERRORF(reporter, "Error creating proxy for rectangle texture.");
+                GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
+                continue;
+            }
         }
 
-        test_read_pixels(reporter, context, rectangleTexture.get(), refPixels);
+        test_basic_draw_as_src(reporter, context, rectProxy, refPixels);
 
-        test_basic_draw(reporter, context, rectangleTexture.get(), refPixels);
+        test_copy_surface_src(reporter, context, rectProxy.get(), refPixels);
 
-        test_copy_surface_src(reporter, context, rectangleTexture.get(), refPixels);
+        sk_sp<GrSurfaceContext> rectContext = context->contextPriv().makeWrappedSurfaceContext(
+                                                                    std::move(rectProxy), nullptr);
+        SkASSERT(rectContext);
 
-        test_copy_surface_dst(reporter, context, rectangleTexture.get());
+        test_read_pixels(reporter, context, rectContext.get(), refPixels);
 
-        test_write_pixels(reporter, context, rectangleTexture.get());
+        test_copy_surface_dst(reporter, context, rectContext.get());
 
-        test_clear(reporter, context, rectangleTexture.get());
+        test_write_pixels(reporter, context, rectContext.get());
+
+        test_clear(reporter, context, rectContext.get());
 
         GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
     }