Revert "Reland "Revert "Use ManagedBackendTexture in place of TestUtils backend texture helpers."""

This reverts commit 4efaf5e9feada3eddf286fb362f60d3b11a24e34.

Cq-Include-Trybots: luci.skia.skia.primary:Test-Win10-MSVC-Golo-GPU-QuadroP400-x86_64-Debug-All-Direct3D,Test-Win10-Clang-ShuttleA-GPU-RadeonHD7770-x86_64-Debug-All-Direct3D
Change-Id: I0f5f1c427e8892a67b027b0fbe4863d9fcee2363
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/325863
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/dm/DMGpuTestProcs.cpp b/dm/DMGpuTestProcs.cpp
index 30249f5..b81d56a 100644
--- a/dm/DMGpuTestProcs.cpp
+++ b/dm/DMGpuTestProcs.cpp
@@ -75,7 +75,8 @@
             // In case the test changed the current context make sure we move it back before
             // calling flush.
             ctxInfo.testContext()->makeCurrent();
-            ctxInfo.directContext()->flushAndSubmit();
+            // Sync so any release/finished procs get called.
+            ctxInfo.directContext()->flushAndSubmit(/*sync*/true);
         }
     }
 }
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 1ac89a6..aeb3946 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1482,22 +1482,18 @@
             break;
         case SkCommandLineConfigGpu::SurfType::kBackendTexture:
             surface = sk_gpu_test::MakeBackendTextureSurface(context,
-                                                             info.dimensions(),
+                                                             info,
                                                              kTopLeft_GrSurfaceOrigin,
                                                              fSampleCount,
-                                                             info.colorType(),
-                                                             info.refColorSpace(),
                                                              GrMipmapped::kNo,
                                                              GrProtected::kNo,
                                                              &props);
             break;
         case SkCommandLineConfigGpu::SurfType::kBackendRenderTarget:
             surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
-                                                                  info.dimensions(),
+                                                                  info,
                                                                   kBottomLeft_GrSurfaceOrigin,
                                                                   fSampleCount,
-                                                                  info.colorType(),
-                                                                  info.refColorSpace(),
                                                                   GrProtected::kNo,
                                                                   &props);
             break;
diff --git a/tests/DeferredDisplayListTest.cpp b/tests/DeferredDisplayListTest.cpp
index f4b4494..6e78cb6 100644
--- a/tests/DeferredDisplayListTest.cpp
+++ b/tests/DeferredDisplayListTest.cpp
@@ -44,6 +44,7 @@
 #include "tests/TestUtils.h"
 #include "tools/gpu/BackendSurfaceFactory.h"
 #include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 #include <initializer_list>
 #include <memory>
@@ -787,10 +788,14 @@
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
     auto dContext = ctxInfo.directContext();
 
-    GrBackendTexture backendTex;
-    CreateBackendTexture(dContext, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
-            SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
-    if (!backendTex.isValid()) {
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
+                                                                    kSize,
+                                                                    kSize,
+                                                                    kRGBA_8888_SkColorType,
+                                                                    GrMipmapped::kNo,
+                                                                    GrRenderable::kNo,
+                                                                    GrProtected::kNo);
+    if (!mbet) {
         return;
     }
 
@@ -798,7 +803,6 @@
 
     sk_sp<SkSurface> s = params.make(dContext);
     if (!s) {
-        dContext->deleteBackendTexture(backendTex);
         return;
     }
 
@@ -812,20 +816,21 @@
 
     auto rContext = canvas->recordingContext();
     if (!rContext) {
-        s = nullptr;
-        dContext->deleteBackendTexture(backendTex);
         return;
     }
 
     // Wrapped Backend Textures are not supported in DDL
     TextureReleaseChecker releaseChecker;
-    sk_sp<SkImage> image =
-            SkImage::MakeFromTexture(rContext, backendTex, kTopLeft_GrSurfaceOrigin,
-                                     kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
-                                     TextureReleaseChecker::Release, &releaseChecker);
+    sk_sp<SkImage> image = SkImage::MakeFromTexture(
+            rContext,
+            mbet->texture(),
+            kTopLeft_GrSurfaceOrigin,
+            kRGBA_8888_SkColorType,
+            kPremul_SkAlphaType,
+            nullptr,
+            sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+            mbet->releaseContext(TextureReleaseChecker::Release, &releaseChecker));
     REPORTER_ASSERT(reporter, !image);
-
-    dContext->deleteBackendTexture(backendTex);
 }
 
 static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
@@ -989,16 +994,14 @@
     SkSurfaceCharacterization characterization;
     SkAssertResult(s->characterize(&characterization));
 
-    GrBackendTexture backendTexture;
-
-    if (!CreateBackendTexture(context, &backendTexture, ii, SkColors::kCyan, GrMipmapped::kNo,
-                              GrRenderable::kNo)) {
-        REPORTER_ASSERT(reporter, false);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(context, ii);
+    if (!mbet) {
+        ERRORF(reporter, "Could not make texture.");
         return;
     }
 
     FulfillInfo fulfillInfo;
-    fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
+    fulfillInfo.fTex = SkPromiseImageTexture::Make(mbet->texture());
 
     sk_sp<SkDeferredDisplayList> ddl;
 
@@ -1050,8 +1053,6 @@
 
     REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
     fulfillInfo.fTex.reset();
-
-    DeleteBackendTexture(context, backendTexture);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/EGLImageTest.cpp b/tests/EGLImageTest.cpp
index d1e75a8..34d3d57 100644
--- a/tests/EGLImageTest.cpp
+++ b/tests/EGLImageTest.cpp
@@ -17,22 +17,20 @@
 #include "tests/Test.h"
 #include "tests/TestUtils.h"
 #include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 #include "tools/gpu/gl/GLTestContext.h"
 
 #ifdef SK_GL
 
 using sk_gpu_test::GLTestContext;
 
-static void cleanup(GLTestContext* glctx0, GrGLuint texID0, GLTestContext* glctx1,
-                    sk_sp<GrDirectContext> dContext, GrBackendTexture* backendTex1,
+static void cleanup(GLTestContext* glctx0,
+                    GrGLuint texID0,
+                    GLTestContext* glctx1,
+                    sk_sp<GrDirectContext> dContext,
                     GrEGLImage image1) {
     if (glctx1) {
         glctx1->makeCurrent();
-        if (dContext) {
-            if (backendTex1 && backendTex1->isValid()) {
-                dContext->deleteBackendTexture(*backendTex1);
-            }
-        }
         if (GR_EGL_NO_IMAGE != image1) {
             glctx1->destroyEGLImage(image1);
         }
@@ -64,19 +62,18 @@
         return;
     }
     sk_sp<GrDirectContext> context1 = GrDirectContext::MakeGL(sk_ref_sp(glCtx1->gl()));
-    GrBackendTexture backendTexture1;
     GrEGLImage image = GR_EGL_NO_IMAGE;
     GrGLTextureInfo externalTexture;
     externalTexture.fID = 0;
 
     if (!context1) {
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
     if (!glCtx1->gl()->hasExtension("EGL_KHR_image") ||
         !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
@@ -86,25 +83,25 @@
     context1->flushAndSubmit();
     static const int kSize = 100;
 
-    CreateBackendTexture(context1.get(), &backendTexture1, kSize, kSize, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
-                         GrProtected::kNo);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            context1.get(), kSize, kSize, kRGBA_8888_SkColorType, GrMipmapped::kNo,
+            GrRenderable::kNo, GrProtected::kNo);
 
-    if (!backendTexture1.isValid()) {
+    if (!mbet) {
         ERRORF(reporter, "Error creating texture for EGL Image");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
     GrGLTextureInfo texInfo;
-    if (!backendTexture1.getGLTextureInfo(&texInfo)) {
+    if (!mbet->texture().getGLTextureInfo(&texInfo)) {
         ERRORF(reporter, "Failed to get GrGLTextureInfo");
         return;
     }
 
     if (GR_GL_TEXTURE_2D != texInfo.fTarget) {
         ERRORF(reporter, "Expected backend texture to be 2D");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
@@ -112,7 +109,7 @@
     image = glCtx1->texture2DToEGLImage(texInfo.fID);
     if (GR_EGL_NO_IMAGE == image) {
         ERRORF(reporter, "Error creating EGL Image from texture");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
@@ -147,7 +144,7 @@
     externalTexture.fFormat = GR_GL_RGBA8;
     if (0 == externalTexture.fID) {
         ERRORF(reporter, "Error converting EGL Image back to texture");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
@@ -163,7 +160,7 @@
             backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
     if (!texProxy) {
         ERRORF(reporter, "Error wrapping external texture in GrTextureProxy.");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
     GrSwizzle swizzle =
@@ -174,7 +171,7 @@
 
     if (!surfaceContext) {
         ERRORF(reporter, "Error wrapping external texture in GrSurfaceContext.");
-        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+        cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
         return;
     }
 
@@ -206,7 +203,7 @@
     TestCopyFromSurface(reporter, context0, surfaceContext->asSurfaceProxy(),
                         surfaceContext->origin(), colorType, pixels.get(), "EGLImageTest-copy");
 
-    cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, &backendTexture1, image);
+    cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
 }
 
 #endif  // SK_GL
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index ec90a81..6a5199e 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -28,6 +28,9 @@
 #include "src/image/SkSurface_Gpu.h"
 #include "tests/Test.h"
 #include "tests/TestUtils.h"
+#include "tools/gpu/BackendSurfaceFactory.h"
+#include "tools/gpu/BackendTextureImageFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 static constexpr int kSize = 8;
 
@@ -44,42 +47,50 @@
             // createBackendTexture currently doesn't support uploading data to mip maps
             // so we don't send any. However, we pretend there is data for the checks below which is
             // fine since we are never actually using these textures for any work on the gpu.
-            GrBackendTexture backendTex;
-            CreateBackendTexture(dContext, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
-                                 SkColors::kTransparent, mipMapped, renderable);
+            auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext,
+                                                                         kSize,
+                                                                         kSize,
+                                                                         kRGBA_8888_SkColorType,
+                                                                         SkColors::kTransparent,
+                                                                         mipMapped,
+                                                                         renderable,
+                                                                         GrProtected::kNo);
 
             sk_sp<GrTextureProxy> proxy;
             sk_sp<SkImage> image;
             if (GrRenderable::kYes == renderable) {
                 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
-                                                                           dContext,
-                                                                           backendTex,
-                                                                           kTopLeft_GrSurfaceOrigin,
-                                                                           0,
-                                                                           kRGBA_8888_SkColorType,
-                                                                           nullptr,
-                                                                           nullptr);
+                        dContext,
+                        mbet->texture(),
+                        kTopLeft_GrSurfaceOrigin,
+                        0,
+                        kRGBA_8888_SkColorType,
+                        /*color space*/ nullptr,
+                        /*surface props*/ nullptr,
+                        sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+                        mbet->releaseContext());
 
                 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
                 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
             } else {
-                image = SkImage::MakeFromTexture(dContext, backendTex,
+                image = SkImage::MakeFromTexture(dContext,
+                                                 mbet->texture(),
                                                  kTopLeft_GrSurfaceOrigin,
                                                  kRGBA_8888_SkColorType,
-                                                 kPremul_SkAlphaType, nullptr,
-                                                 nullptr, nullptr);
+                                                 kPremul_SkAlphaType,
+                                                 /* color space */ nullptr,
+                                                 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+                                                 mbet->releaseContext());
                 const GrSurfaceProxyView* view = as_IB(image)->view(dContext);
                 REPORTER_ASSERT(reporter, view);
                 if (!view) {
-                    dContext->deleteBackendTexture(backendTex);
-                    return;
+                    continue;
                 }
                 proxy = view->asTextureProxyRef();
             }
             REPORTER_ASSERT(reporter, proxy);
             if (!proxy) {
-                dContext->deleteBackendTexture(backendTex);
-                return;
+                continue;
             }
 
             REPORTER_ASSERT(reporter, proxy->isInstantiated());
@@ -87,8 +98,7 @@
             GrTexture* texture = proxy->peekTexture();
             REPORTER_ASSERT(reporter, texture);
             if (!texture) {
-                dContext->deleteBackendTexture(backendTex);
-                return;
+                continue;
             }
 
             if (GrMipmapped::kYes == mipMapped) {
@@ -101,7 +111,6 @@
             } else {
                 REPORTER_ASSERT(reporter, GrMipmapped::kNo == texture->mipmapped());
             }
-            dContext->deleteBackendTexture(backendTex);
         }
     }
 }
@@ -116,20 +125,14 @@
 
     for (auto betMipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
         for (auto requestMipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
-            GrBackendTexture backendTex;
-            CreateBackendTexture(dContext, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
-                                 SkColors::kTransparent, betMipMapped, GrRenderable::kNo);
-
-            sk_sp<SkImage> image = SkImage::MakeFromTexture(dContext, backendTex,
-                                                            kTopLeft_GrSurfaceOrigin,
-                                                            kRGBA_8888_SkColorType,
-                                                            kPremul_SkAlphaType, nullptr,
-                                                            nullptr, nullptr);
+            auto ii =
+                    SkImageInfo::Make({kSize, kSize}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+            sk_sp<SkImage> image = sk_gpu_test::MakeBackendTextureImage(
+                    dContext, ii, SkColors::kTransparent, betMipMapped);
 
             GrTextureProxy* proxy = as_IB(image)->peekProxy();
             REPORTER_ASSERT(reporter, proxy);
             if (!proxy) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
@@ -138,7 +141,6 @@
             sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
             REPORTER_ASSERT(reporter, texture);
             if (!texture) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
@@ -147,7 +149,6 @@
                     kPremul_SkAlphaType, nullptr);
             REPORTER_ASSERT(reporter, imageGen);
             if (!imageGen) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
@@ -160,7 +161,6 @@
 
             REPORTER_ASSERT(reporter, genProxy);
             if (!genProxy) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
@@ -172,17 +172,16 @@
 
             REPORTER_ASSERT(reporter, genProxy->isInstantiated());
             if (!genProxy->isInstantiated()) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
             GrTexture* genTexture = genProxy->peekTexture();
             REPORTER_ASSERT(reporter, genTexture);
             if (!genTexture) {
-                dContext->deleteBackendTexture(backendTex);
                 return;
             }
 
+            GrBackendTexture backendTex = texture->getBackendTexture();
             GrBackendTexture genBackendTex = genTexture->getBackendTexture();
 
             if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
@@ -252,14 +251,6 @@
             } else {
                 REPORTER_ASSERT(reporter, false);
             }
-
-            // Must make sure the uses of the backend texture have finished (we possibly have a
-            // queued up copy) before we delete the backend texture.
-            dContext->flushAndSubmit();
-
-            dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
-
-            dContext->deleteBackendTexture(backendTex);
         }
     }
 }
@@ -278,28 +269,24 @@
         for (auto isWrapped : {false, true}) {
             GrMipmapped mipMapped = willUseMips ? GrMipmapped::kYes : GrMipmapped::kNo;
             sk_sp<SkSurface> surface;
-            GrBackendTexture backendTex;
-            CreateBackendTexture(dContext, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
-                                 SkColors::kTransparent, mipMapped, GrRenderable::kYes);
+            SkImageInfo info =
+                    SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
             if (isWrapped) {
-                surface = SkSurface::MakeFromBackendTexture(dContext,
-                                                            backendTex,
-                                                            kTopLeft_GrSurfaceOrigin,
-                                                            0,
-                                                            kRGBA_8888_SkColorType,
-                                                            nullptr,
-                                                            nullptr);
+                surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
+                                                                 info,
+                                                                 kTopLeft_GrSurfaceOrigin,
+                                                                 /* sample count */ 1,
+                                                                 mipMapped);
             } else {
-                SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
-                                                     kPremul_SkAlphaType);
-                surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, info, 0,
-                                                      kTopLeft_GrSurfaceOrigin, nullptr,
+                surface = SkSurface::MakeRenderTarget(dContext,
+                                                      SkBudgeted::kYes,
+                                                      info,
+                                                      /* sample count */ 1,
+                                                      kTopLeft_GrSurfaceOrigin,
+                                                      nullptr,
                                                       willUseMips);
             }
             REPORTER_ASSERT(reporter, surface);
-            if (!surface) {
-                dContext->deleteBackendTexture(backendTex);
-            }
             SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
             GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipmapped());
@@ -310,21 +297,12 @@
 
             sk_sp<SkImage> image = surface->makeImageSnapshot();
             REPORTER_ASSERT(reporter, image);
-            if (!image) {
-                dContext->deleteBackendTexture(backendTex);
-            }
             texProxy = as_IB(image)->peekProxy();
             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipmapped());
 
             texProxy->instantiate(resourceProvider);
             texture = texProxy->peekTexture();
             REPORTER_ASSERT(reporter, mipMapped == texture->mipmapped());
-
-            // Must flush the dContext to make sure all the cmds (copies, etc.) from above are sent
-            // to the gpu before we delete the backendHandle.
-            dContext->flushAndSubmit();
-            dContext->priv().getGpu()->testingOnly_flushGpuAndSync();
-            dContext->deleteBackendTexture(backendTex);
         }
     }
 }
diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp
index 5ed939e..9eb370d 100644
--- a/tests/GrPorterDuffTest.cpp
+++ b/tests/GrPorterDuffTest.cpp
@@ -17,8 +17,8 @@
 #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
 #include "src/gpu/gl/GrGLCaps.h"
 #include "src/gpu/ops/GrMeshDrawOp.h"
-#include "tests/TestUtils.h"
 #include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -999,16 +999,15 @@
         SK_ABORT("Mock context failed to honor request for no ARB_blend_func_extended.");
     }
 
-    GrBackendTexture backendTex;
-    CreateBackendTexture(ctx, &backendTex, 100, 100, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo);
-
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            ctx, 100, 100, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo);
     GrXferProcessor::DstProxyView fakeDstProxyView;
     {
         sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
-                backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
-        GrSwizzle swizzle = caps.getReadSwizzle(backendTex.getBackendFormat(),
-                                                GrColorType::kRGBA_8888);
+                mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType,
+                mbet->refCountedCallback());
+        GrSwizzle swizzle =
+                caps.getReadSwizzle(mbet->texture().getBackendFormat(), GrColorType::kRGBA_8888);
         fakeDstProxyView.setProxyView({std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle});
     }
 
@@ -1034,5 +1033,4 @@
             }
         }
     }
-    ctx->deleteBackendTexture(backendTex);
 }
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index ac488a2..05dd427 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -22,6 +22,8 @@
 #include "src/gpu/GrTexture.h"
 #include "tests/Test.h"
 #include "tests/TestUtils.h"
+#include "tools/gpu/BackendTextureImageFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 // Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture
 // and render targets to GrSurface all work as expected.
@@ -357,11 +359,11 @@
     // that they'd succeed if the texture wasn't kRead. We want to be sure we're failing with
     // kRead for the right reason.
     for (auto ioType : {kRead_GrIOType, kRW_GrIOType}) {
-        auto backendTex = dContext->createBackendTexture(&srcPixmap, 1,
-                                                         GrRenderable::kYes, GrProtected::kNo);
-
-        auto proxy = proxyProvider->wrapBackendTexture(
-                backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, ioType);
+        auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(
+                dContext, srcPixmap, GrRenderable::kNo, GrProtected::kNo);
+        auto proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
+                                                       GrWrapCacheable::kNo, ioType,
+                                                       mbet->refCountedCallback());
         GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
                                                                     GrColorType::kRGBA_8888);
         GrSurfaceProxyView view(proxy, kTopLeft_GrSurfaceOrigin, swizzle);
@@ -415,51 +417,45 @@
 
         // Mip regen should not work with a read only texture.
         if (dContext->priv().caps()->mipmapSupport()) {
-            DeleteBackendTexture(dContext, backendTex);
-            backendTex = dContext->createBackendTexture(
-                    kSize, kSize, kRGBA_8888_SkColorType,
-                    SkColors::kTransparent, GrMipmapped::kYes, GrRenderable::kYes,
-                    GrProtected::kNo);
-            proxy = proxyProvider->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership,
-                                                      GrWrapCacheable::kNo, ioType);
+            mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
+                                                                       kSize,
+                                                                       kSize,
+                                                                       kRGBA_8888_SkColorType,
+                                                                       GrMipmapped::kYes,
+                                                                       GrRenderable::kNo,
+                                                                       GrProtected::kNo);
+            proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
+                                                      GrWrapCacheable::kNo, ioType,
+                                                      mbet->refCountedCallback());
             dContext->flushAndSubmit();
             proxy->peekTexture()->markMipmapsDirty();  // avoids assert in GrGpu.
             auto regenResult =
                     dContext->priv().getGpu()->regenerateMipMapLevels(proxy->peekTexture());
             REPORTER_ASSERT(reporter, regenResult == (ioType == kRW_GrIOType));
         }
-        DeleteBackendTexture(dContext, backendTex);
     }
 }
 
 static const int kSurfSize = 10;
 
 static sk_sp<GrTexture> make_wrapped_texture(GrDirectContext* dContext, GrRenderable renderable) {
-    GrBackendTexture backendTexture;
-    CreateBackendTexture(dContext, &backendTexture, kSurfSize, kSurfSize, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, renderable, GrProtected::kNo);
-    SkASSERT(backendTexture.isValid());
-    sk_sp<GrTexture> texture;
-    if (GrRenderable::kYes == renderable) {
-        texture = dContext->priv().resourceProvider()->wrapRenderableBackendTexture(
-                backendTexture, 1, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext, kSurfSize, kSurfSize, kRGBA_8888_SkColorType, GrMipmapped::kNo, renderable);
+    SkASSERT(mbet);
+    sk_sp<GrTextureProxy> proxy;
+    if (renderable == GrRenderable::kYes) {
+        proxy = dContext->priv().proxyProvider()->wrapRenderableBackendTexture(
+                mbet->texture(), 1, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
+                mbet->refCountedCallback());
     } else {
-        texture = dContext->priv().resourceProvider()->wrapBackendTexture(
-                backendTexture, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
+        proxy = dContext->priv().proxyProvider()->wrapBackendTexture(
+                mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType,
+                mbet->refCountedCallback());
     }
-    // Add a release proc that deletes the GrBackendTexture.
-    struct ReleaseContext {
-        GrDirectContext* fDContext;
-        GrBackendTexture fBackendTexture;
-    };
-    auto release = [](void* rc) {
-        auto releaseContext = static_cast<ReleaseContext*>(rc);
-        auto dContext = releaseContext->fDContext;
-        dContext->deleteBackendTexture(releaseContext->fBackendTexture);
-        delete releaseContext;
-    };
-    texture->setRelease(release, new ReleaseContext{dContext, backendTexture});
-    return texture;
+    if (!proxy) {
+        return nullptr;
+    }
+    return sk_ref_sp(proxy->peekTexture());
 }
 
 static sk_sp<GrTexture> make_normal_texture(GrDirectContext* dContext, GrRenderable renderable) {
@@ -777,22 +773,11 @@
             // is a wrapped-texture backed image.
             surf->getCanvas()->clear(SK_ColorWHITE);
             auto img1 = surf->makeImageSnapshot();
-
-            GrBackendTexture backendTexture;
-
-            if (!CreateBackendTexture(dContext, &backendTexture, info, SkColors::kBlack,
-                                      GrMipmapped::kNo, GrRenderable::kNo)) {
-                REPORTER_ASSERT(reporter, false);
-                continue;
-            }
-
-            auto img2 = SkImage::MakeFromTexture(dContext, backendTexture, kTopLeft_GrSurfaceOrigin,
-                                                 info.colorType(), info.alphaType(), nullptr);
+            auto img2 = sk_gpu_test::MakeBackendTextureImage(dContext, info, SkColors::kBlack);
+            REPORTER_ASSERT(reporter, img1 && img2);
             surf->getCanvas()->drawImage(std::move(img1), 0, 0);
             surf->getCanvas()->drawImage(std::move(img2), 1, 1);
             idleTexture.reset();
-
-            DeleteBackendTexture(dContext, backendTexture);
         }
     }
 }
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 2a9c4da..92222bc 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -36,9 +36,9 @@
 #include "src/image/SkImage_Base.h"
 #include "src/image/SkImage_GpuYUVA.h"
 #include "tests/Test.h"
-#include "tests/TestUtils.h"
 #include "tools/Resources.h"
 #include "tools/ToolUtils.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 using namespace sk_gpu_test;
 
@@ -487,19 +487,17 @@
         SkColorType colorType = static_cast<SkColorType>(ct);
         bool can = dContext->colorTypeSupportedAsImage(colorType);
 
-        GrBackendTexture backendTex;
-        CreateBackendTexture(dContext, &backendTex, kSize, kSize, colorType, SkColors::kTransparent,
-                             GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
-
-        auto img = SkImage::MakeFromTexture(dContext, backendTex, kTopLeft_GrSurfaceOrigin,
+        auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+                dContext, kSize, kSize, colorType, GrMipmapped::kNo, GrRenderable::kNo);
+        if (!mbet) {
+            ERRORF(reporter, "Could not create texture with color type %d.", colorType);
+            continue;
+        }
+        auto img = SkImage::MakeFromTexture(dContext, mbet->texture(), kTopLeft_GrSurfaceOrigin,
                                             colorType, kOpaque_SkAlphaType, nullptr);
         REPORTER_ASSERT(reporter, can == SkToBool(img),
                         "colorTypeSupportedAsImage:%d, actual:%d, ct:%d", can, SkToBool(img),
                         colorType);
-
-        img.reset();
-        dContext->flushAndSubmit();
-        dContext->deleteBackendTexture(backendTex);
     }
 }
 
@@ -832,27 +830,36 @@
 
     auto dContext = ctxInfo.directContext();
 
-    SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
-                                       kPremul_SkAlphaType);
-    GrBackendTexture backendTex;
-    if (!CreateBackendTexture(dContext, &backendTex, ii, SkColors::kRed, GrMipmapped::kNo,
-                              GrRenderable::kNo)) {
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
+                                                                    kWidth,
+                                                                    kHeight,
+                                                                    kRGBA_8888_SkColorType,
+                                                                    GrMipmapped::kNo,
+                                                                    GrRenderable::kNo,
+                                                                    GrProtected::kNo);
+    if (!mbet) {
         ERRORF(reporter, "couldn't create backend texture\n");
     }
 
     TextureReleaseChecker releaseChecker;
     GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
-    sk_sp<SkImage> refImg(
-        SkImage::MakeFromTexture(dContext, backendTex, texOrigin, kRGBA_8888_SkColorType,
-                                 kPremul_SkAlphaType, nullptr,
-                                 TextureReleaseChecker::Release, &releaseChecker));
+    sk_sp<SkImage> refImg = SkImage::MakeFromTexture(
+            dContext,
+            mbet->texture(),
+            texOrigin,
+            kRGBA_8888_SkColorType,
+            kPremul_SkAlphaType,
+            /*color space*/nullptr,
+            sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+            mbet->releaseContext(TextureReleaseChecker::Release, &releaseChecker));
 
     GrSurfaceOrigin readBackOrigin;
     GrBackendTexture readBackBackendTex = refImg->getBackendTexture(false, &readBackOrigin);
-    if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex)) {
+    if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, mbet->texture())) {
         ERRORF(reporter, "backend mismatch\n");
     }
-    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex));
+    REPORTER_ASSERT(reporter,
+                    GrBackendTexture::TestingOnly_Equals(readBackBackendTex, mbet->texture()));
     if (readBackOrigin != texOrigin) {
         ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
     }
@@ -862,8 +869,6 @@
     REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
     refImg.reset(nullptr); // force a release of the image
     REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
-
-    DeleteBackendTexture(dContext, backendTex);
 }
 
 static void test_cross_context_image(skiatest::Reporter* reporter, const GrContextOptions& options,
diff --git a/tests/PromiseImageTest.cpp b/tests/PromiseImageTest.cpp
index 126b44b..4b73db0 100644
--- a/tests/PromiseImageTest.cpp
+++ b/tests/PromiseImageTest.cpp
@@ -15,7 +15,7 @@
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrTexture.h"
 #include "src/image/SkImage_Gpu.h"
-#include "tests/TestUtils.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 using namespace sk_gpu_test;
 
@@ -270,23 +270,37 @@
                 continue;
             }
 
-            GrBackendTexture backendTex;
-            CreateBackendTexture(ctx, &backendTex, kWidth, kHeight, kAlpha_8_SkColorType,
-                                 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
-                                 GrProtected::kNo);
-            REPORTER_ASSERT(reporter, backendTex.isValid());
+            auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(ctx,
+                                                                            kWidth,
+                                                                            kHeight,
+                                                                            kAlpha_8_SkColorType,
+                                                                            GrMipmapped::kNo,
+                                                                            GrRenderable::kNo);
+            if (!mbet) {
+                ERRORF(reporter, "Could not create texture alpha texture.");
+                continue;
+            }
 
             SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType,
                                                  kPremul_SkAlphaType);
             sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
             SkCanvas* canvas = surface->getCanvas();
 
-            PromiseTextureChecker promiseChecker(backendTex, reporter, false);
+            PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false);
             sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(
-                    ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipmapped::kNo,
-                    kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
-                    PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
-                    PromiseTextureChecker::Done, &promiseChecker,
+                    ctx,
+                    mbet->texture().getBackendFormat(),
+                    kWidth,
+                    kHeight,
+                    GrMipmapped::kNo,
+                    kTopLeft_GrSurfaceOrigin,
+                    kAlpha_8_SkColorType,
+                    kPremul_SkAlphaType,
+                    /*color space*/ nullptr,
+                    PromiseTextureChecker::Fulfill,
+                    PromiseTextureChecker::Release,
+                    PromiseTextureChecker::Done,
+                    &promiseChecker,
                     SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
             REPORTER_ASSERT(reporter, image);
 
@@ -377,15 +391,12 @@
 
     auto dContext = ctxInfo.directContext();
 
-    // Do all this just to get a valid backend format for the image.
-    GrBackendTexture backendTex;
-    CreateBackendTexture(dContext, &backendTex, kWidth, kHeight, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
-                         GrProtected::kNo);
-    REPORTER_ASSERT(reporter, backendTex.isValid());
-    GrBackendFormat backendFormat = backendTex.getBackendFormat();
-    REPORTER_ASSERT(reporter, backendFormat.isValid());
-    dContext->deleteBackendTexture(backendTex);
+    GrBackendFormat backendFormat =
+            dContext->defaultBackendFormat(kRGBA_8888_SkColorType, GrRenderable::kYes);
+    if (!backendFormat.isValid()) {
+        ERRORF(reporter, "No valid default kRGBA_8888 texture format.");
+        return;
+    }
 
     struct Counts {
         int fFulfillCount = 0;
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
index 0c1f72a..09de88b 100644
--- a/tests/ProxyTest.cpp
+++ b/tests/ProxyTest.cpp
@@ -7,8 +7,6 @@
 
 // This is a GPU-backend specific test.
 
-#include "tests/Test.h"
-
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrDirectContext.h"
 #include "src/gpu/GrContextPriv.h"
@@ -22,6 +20,8 @@
 #include "src/gpu/GrTexture.h"
 #include "src/gpu/GrTextureProxy.h"
 #include "src/gpu/SkGr.h"
+#include "tests/Test.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 #ifdef SK_GL
 #include "src/gpu/gl/GrGLDefines.h"
 #include "src/gpu/gl/GrGLUtil.h"
@@ -265,47 +265,57 @@
 
             // Tests wrapBackendTexture that is only renderable
             {
-                GrBackendTexture backendTex;
-                CreateBackendTexture(direct, &backendTex, kWidthHeight, kWidthHeight, colorType,
-                                     SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
-                                     GrProtected::kNo);
-
+                auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
+                                                                                kWidthHeight,
+                                                                                kWidthHeight,
+                                                                                colorType,
+                                                                                GrMipmapped::kNo,
+                                                                                GrRenderable::kYes);
+                if (!mbet) {
+                    ERRORF(reporter,
+                           "Could not create renderable backend texture of color type %d",
+                           colorType);
+                    continue;
+                }
                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapRenderableBackendTexture(
-                        backendTex, supportedNumSamples, kBorrow_GrWrapOwnership,
+                        mbet->texture(), supportedNumSamples, kBorrow_GrWrapOwnership,
                         GrWrapCacheable::kNo, nullptr);
                 if (!sProxy) {
-                    direct->deleteBackendTexture(backendTex);
-                    continue;  // This can fail on Mesa
+                    ERRORF(reporter, "wrapRenderableBackendTexture failed");
+                    continue;
                 }
 
                 check_surface(reporter, sProxy.get(), kWidthHeight, kWidthHeight, SkBudgeted::kNo);
                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
                                    supportedNumSamples, SkBackingFit::kExact,
                                    caps.maxWindowRectangles());
-
-                direct->deleteBackendTexture(backendTex);
             }
 
-            // Tests wrapBackendTexture that is only textureable
             {
-                // Internal offscreen texture
-                GrBackendTexture backendTex;
-                CreateBackendTexture(direct, &backendTex, kWidthHeight, kWidthHeight, colorType,
-                                     SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
-                                     GrProtected::kNo);
-
+                // Tests wrapBackendTexture that is only textureable
+                auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
+                                                                                kWidthHeight,
+                                                                                kWidthHeight,
+                                                                                colorType,
+                                                                                GrMipmapped::kNo,
+                                                                                GrRenderable::kNo);
+                if (!mbet) {
+                    ERRORF(reporter,
+                           "Could not create non-renderable backend texture of color type %d",
+                           colorType);
+                    continue;
+                }
                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapBackendTexture(
-                        backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
+                        mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
+                        kRead_GrIOType, mbet->refCountedCallback());
                 if (!sProxy) {
-                    direct->deleteBackendTexture(backendTex);
+                    ERRORF(reporter, "wrapBackendTexture failed");
                     continue;
                 }
 
                 check_surface(reporter, sProxy.get(), kWidthHeight, kWidthHeight, SkBudgeted::kNo);
                 check_texture(reporter, resourceProvider, sProxy->asTextureProxy(),
                               SkBackingFit::kExact);
-
-                direct->deleteBackendTexture(backendTex);
             }
         }
     }
diff --git a/tests/ResourceAllocatorTest.cpp b/tests/ResourceAllocatorTest.cpp
index 69c3e01..1d1e7e1 100644
--- a/tests/ResourceAllocatorTest.cpp
+++ b/tests/ResourceAllocatorTest.cpp
@@ -17,7 +17,7 @@
 #include "src/gpu/GrTexture.h"
 #include "src/gpu/GrTextureProxy.h"
 #include "tests/Test.h"
-#include "tests/TestUtils.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 struct ProxyParams {
     int             fSize;
@@ -36,27 +36,24 @@
                                       GrMipmapped::kNo, p.fFit, p.fBudgeted, GrProtected::kNo);
 }
 
-static sk_sp<GrSurfaceProxy> make_backend(GrDirectContext* dContext,
-                                          const ProxyParams& p,
-                                          GrBackendTexture* backendTex) {
+static sk_sp<GrSurfaceProxy> make_backend(GrDirectContext* dContext, const ProxyParams& p) {
     GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
 
     SkColorType skColorType = GrColorTypeToSkColorType(p.fColorType);
     SkASSERT(SkColorType::kUnknown_SkColorType != skColorType);
 
-    CreateBackendTexture(dContext, backendTex, p.fSize, p.fSize, skColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext, p.fSize, p.fSize, skColorType, GrMipmapped::kNo, GrRenderable::kNo);
 
-    if (!backendTex->isValid()) {
+    if (!mbet) {
         return nullptr;
     }
 
-    return proxyProvider->wrapBackendTexture(*backendTex, kBorrow_GrWrapOwnership,
-                                             GrWrapCacheable::kNo, kRead_GrIOType);
-}
-
-static void cleanup_backend(GrDirectContext* dContext, const GrBackendTexture& backendTex) {
-    dContext->deleteBackendTexture(backendTex);
+    return proxyProvider->wrapBackendTexture(mbet->texture(),
+                                             kBorrow_GrWrapOwnership,
+                                             GrWrapCacheable::kNo,
+                                             kRead_GrIOType,
+                                             mbet->refCountedCallback());
 }
 
 // Basic test that two proxies with overlapping intervals and compatible descriptors are
@@ -216,14 +213,11 @@
         TestCase t[1] = {
                 {{64, kNotRT, kRGBA, kE, 1, kNotB}, {64, kNotRT, kRGBA, kE, 1, kNotB}, kDontShare}};
 
-        GrBackendTexture backEndTex;
-        sk_sp<GrSurfaceProxy> p1 = make_backend(direct, t[0].fP1, &backEndTex);
+        sk_sp<GrSurfaceProxy> p1 = make_backend(direct, t[0].fP1);
         sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, caps, t[0].fP2);
 
         non_overlap_test(reporter, resourceProvider, std::move(p1), std::move(p2),
                          t[0].fExpectation);
-
-        cleanup_backend(direct, backEndTex);
     }
 }
 
@@ -346,18 +340,15 @@
 
     // Wrapped proxy that will be ignored by the resourceAllocator. We use this to try and get the
     // resource allocator fCurOpsTaskIndex to fall behind what it really should be.
-    GrBackendTexture backEndTex;
-    sk_sp<GrSurfaceProxy> proxyWrapped = make_backend(context, params, &backEndTex);
+    sk_sp<GrSurfaceProxy> proxyWrapped = make_backend(context, params);
     if (!proxyWrapped) {
         return;
     }
 
     // Same as above, but we actually need to have at least two intervals that don't go through the
     // resource allocator to expose the index bug.
-    GrBackendTexture backEndTex2;
-    sk_sp<GrSurfaceProxy> proxyWrapped2 = make_backend(context, params, &backEndTex2);
+    sk_sp<GrSurfaceProxy> proxyWrapped2 = make_backend(context, params);
     if (!proxyWrapped2) {
-        cleanup_backend(context, backEndTex);
         return;
     }
 
@@ -398,9 +389,6 @@
     REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
     REPORTER_ASSERT(reporter, 3 == startIndex && 4 == stopIndex);
 
-    cleanup_backend(context, backEndTex);
-    cleanup_backend(context, backEndTex2);
-
     context->setResourceCacheLimit(origMaxBytes);
 }
 
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index d74df1a..aa9913a 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -7,7 +7,11 @@
 
 #include "include/core/SkTypes.h"
 
+#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
 #include "include/gpu/GrDirectContext.h"
+#include "src/core/SkMessageBus.h"
+#include "src/core/SkMipmap.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrGpuResourceCacheAccess.h"
@@ -18,15 +22,10 @@
 #include "src/gpu/GrResourceCache.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrTexture.h"
-#include "tools/gpu/GrContextFactory.h"
-
-#include "include/core/SkCanvas.h"
-#include "include/core/SkSurface.h"
-#include "src/core/SkMessageBus.h"
-#include "src/core/SkMipmap.h"
 #include "src/gpu/SkGr.h"
 #include "tests/Test.h"
-#include "tests/TestUtils.h"
+#include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 #include <thread>
 
@@ -191,51 +190,44 @@
         return;
     }
 
-    GrBackendTexture backendTextures[2];
     static const int kW = 100;
     static const int kH = 100;
 
-    CreateBackendTexture(context, &backendTextures[0], kW, kH, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
-                         GrProtected::kNo);
-    CreateBackendTexture(context, &backendTextures[1], kW, kH, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo,
-                         GrProtected::kNo);
-    REPORTER_ASSERT(reporter, backendTextures[0].isValid());
-    REPORTER_ASSERT(reporter, backendTextures[1].isValid());
-    if (!backendTextures[0].isValid() || !backendTextures[1].isValid()) {
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            context, kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo);
+    GrBackendTexture unmbet = context->createBackendTexture(
+            kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo);
+    if (!mbet || !unmbet.isValid()) {
+        ERRORF(reporter, "Could not create backend texture.");
         return;
     }
 
     context->resetContext();
 
     sk_sp<GrTexture> borrowed(resourceProvider->wrapBackendTexture(
-            backendTextures[0], kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
+            mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
 
     sk_sp<GrTexture> adopted(resourceProvider->wrapBackendTexture(
-            backendTextures[1], kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
+            unmbet, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
 
     REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
     if (!borrowed || !adopted) {
         return;
     }
 
-    borrowed.reset(nullptr);
-    adopted.reset(nullptr);
+    borrowed.reset();
+    adopted.reset();
 
-    context->flushAndSubmit();
+    context->flushAndSubmit(/*sync*/ true);
 
-    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[0]);
-    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[1]);
+    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(mbet->texture());
+    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(unmbet);
 
     REPORTER_ASSERT(reporter, borrowedIsAlive);
     REPORTER_ASSERT(reporter, !adoptedIsAlive);
 
-    if (borrowedIsAlive) {
-        context->deleteBackendTexture(backendTextures[0]);
-    }
     if (adoptedIsAlive) {
-        context->deleteBackendTexture(backendTextures[1]);
+        context->deleteBackendTexture(unmbet);
     }
 
     context->resetContext();
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index fe588cf..c4fc29b 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -29,15 +29,14 @@
 #include "src/image/SkImage_Gpu.h"
 #include "src/image/SkSurface_Gpu.h"
 #include "tests/Test.h"
-#include "tests/TestUtils.h"
+#include "tools/ToolUtils.h"
 #include "tools/gpu/BackendSurfaceFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 #include <functional>
 #include <initializer_list>
 #include <vector>
 
-#include "tools/ToolUtils.h"
-
 static void release_direct_surface_storage(void* pixels, void* context) {
     SkASSERT(pixels == context);
     sk_free(pixels);
@@ -108,19 +107,13 @@
             REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                             colorType, can, SkToBool(surf));
 
-            GrBackendTexture backendTex;
-            CreateBackendTexture(context, &backendTex, kSize, kSize, colorType,
-                                 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
-                                 GrProtected::kNo);
-            surf = SkSurface::MakeFromBackendTexture(context, backendTex,
-                                                     kTopLeft_GrSurfaceOrigin, 0, colorType,
-                                                     nullptr, nullptr);
+            surf = sk_gpu_test::MakeBackendTextureSurface(context,
+                                                          {kSize, kSize},
+                                                          kTopLeft_GrSurfaceOrigin,
+                                                          /*sample cnt*/ 1,
+                                                          colorType);
             REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                             colorType, can, SkToBool(surf));
-
-            surf.reset();
-            context->flushAndSubmit();
-            context->deleteBackendTexture(backendTex);
         }
 
         // The MSAA test only makes sense if the colorType is renderable to begin with.
@@ -133,13 +126,8 @@
             REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                             colorType, can, SkToBool(surf));
 
-            GrBackendTexture backendTex;
-            CreateBackendTexture(context, &backendTex, kSize, kSize, colorType,
-                                 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
-                                 GrProtected::kNo);
-            surf = SkSurface::MakeFromBackendTexture(context, backendTex,
-                                                     kTopLeft_GrSurfaceOrigin, kSampleCnt,
-                                                     colorType, nullptr, nullptr);
+            surf = sk_gpu_test::MakeBackendTextureSurface(
+                    context, {kSize, kSize}, kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType);
             REPORTER_ASSERT(reporter, can == SkToBool(surf),
                             "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
                             colorType);
@@ -147,15 +135,13 @@
             if (surf) {
                 auto rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
                 int storedCnt = rtc->numSamples();
-                int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(
-                        storedCnt, backendTex.getBackendFormat());
+                GrBackendFormat format = rtc->writeSurfaceView().proxy()->backendFormat();
+                int allowedCnt =
+                        context->priv().caps()->getRenderTargetSampleCount(storedCnt, format);
                 REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
                                 "Should store an allowed sample count (%d vs %d)", allowedCnt,
                                 storedCnt);
             }
-            surf.reset();
-            context->flushAndSubmit();
-            context->deleteBackendTexture(backendTex);
         }
 
         for (int sampleCnt : {1, 2}) {
@@ -201,39 +187,27 @@
     for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
 
         SkColorType colorType = static_cast<SkColorType>(ct);
-        int max = context->maxSurfaceSampleCountForColorType(colorType);
-        if (!max) {
+        int maxSampleCnt = context->maxSurfaceSampleCountForColorType(colorType);
+        if (!maxSampleCnt) {
             continue;
         }
-
-        GrBackendTexture backendTex;
-        CreateBackendTexture(context, &backendTex, kSize, kSize, colorType,
-                             SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
-                             GrProtected::kNo);
-        if (!backendTex.isValid()) {
-            continue;
-        }
-        SkScopeExit freeTex([&backendTex, context] {
-            context->deleteBackendTexture(backendTex);
-        });
-
         if (!context->colorTypeSupportedAsSurface(colorType)) {
             continue;
         }
 
         auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
-        auto surf = SkSurface::MakeFromBackendTexture(context, backendTex,
-                                                      kTopLeft_GrSurfaceOrigin, max,
-                                                      colorType, nullptr, nullptr);
-        REPORTER_ASSERT(reporter, surf);
+        auto surf = sk_gpu_test::MakeBackendTextureSurface(
+                context, info, kTopLeft_GrSurfaceOrigin, maxSampleCnt);
         if (!surf) {
+            ERRORF(reporter, "Could not make surface of color type %d.", colorType);
             continue;
         }
         int sampleCnt = ((SkSurface_Gpu*)(surf.get()))
                                 ->getDevice()
                                 ->accessRenderTargetContext()
                                 ->numSamples();
-        REPORTER_ASSERT(reporter, sampleCnt == max, "Exected: %d, actual: %d", max, sampleCnt);
+        REPORTER_ASSERT(reporter, sampleCnt == maxSampleCnt, "Exected: %d, actual: %d",
+                        maxSampleCnt, sampleCnt);
     }
 }
 
@@ -679,9 +653,7 @@
 
 static sk_sp<SkSurface> create_gpu_surface_backend_texture(GrDirectContext* dContext,
                                                            int sampleCnt,
-                                                           const SkColor4f& color,
-                                                           GrBackendTexture* outTexture) {
-
+                                                           const SkColor4f& color) {
     // On Pixel and Pixel2XL's with Adreno 530 and 540s, setting width and height to 10s reliably
     // triggers what appears to be a driver race condition where the 10x10 surface from the
     // OverdrawSurface_gpu test is reused(?) for this surface created by the SurfacePartialDraw_gpu
@@ -705,25 +677,16 @@
     const int kHeight = 100;
 #endif
 
-    SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
-                                       kPremul_SkAlphaType);
-
-    if (!CreateBackendTexture(dContext, outTexture, ii, color,
-                              GrMipmapped::kNo, GrRenderable::kYes)) {
+    auto surf = sk_gpu_test::MakeBackendTextureSurface(dContext,
+                                                       {kWidth, kHeight},
+                                                       kTopLeft_GrSurfaceOrigin,
+                                                       sampleCnt,
+                                                       kRGBA_8888_SkColorType);
+    if (!surf) {
         return nullptr;
     }
-
-    sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(dContext,
-                                                                 *outTexture,
-                                                                 kTopLeft_GrSurfaceOrigin,
-                                                                 sampleCnt,
-                                                                 kRGBA_8888_SkColorType,
-                                                                 nullptr, nullptr);
-    if (!surface) {
-        DeleteBackendTexture(dContext, *outTexture);
-        return nullptr;
-    }
-    return surface;
+    surf->getCanvas()->clear(color);
+    return surf;
 }
 
 static bool supports_readpixels(const GrCaps* caps, SkSurface* surface) {
@@ -738,8 +701,7 @@
 
 static sk_sp<SkSurface> create_gpu_surface_backend_render_target(GrDirectContext* dContext,
                                                                  int sampleCnt,
-                                                                 const SkColor4f& color,
-                                                                 GrBackendTexture* outTexture) {
+                                                                 const SkColor4f& color) {
     const int kWidth = 10;
     const int kHeight = 10;
 
@@ -747,10 +709,7 @@
                                                             {kWidth, kHeight},
                                                             kTopLeft_GrSurfaceOrigin,
                                                             sampleCnt,
-                                                            kRGBA_8888_SkColorType,
-                                                            nullptr,
-                                                            GrProtected::kNo,
-                                                            nullptr);
+                                                            kRGBA_8888_SkColorType);
     if (!surf) {
         return nullptr;
     }
@@ -823,8 +782,7 @@
     const SkColor4f kOrigColor{.67f, .67f, .67f, 1};
     for (auto& surfaceFunc :
          {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
-        GrBackendTexture backendTex;
-        auto surface = surfaceFunc(dContext, 1, kOrigColor, &backendTex);
+        auto surface = surfaceFunc(dContext, 1, kOrigColor);
         if (!surface) {
             ERRORF(reporter, "Could not create GPU SkSurface.");
             return;
@@ -838,7 +796,6 @@
         auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
         test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(),
                                    kOrigColor.toSkColor());
-        dContext->deleteBackendTexture(backendTex);
     }
 }
 
@@ -904,16 +861,9 @@
         // Validate that we can draw to the canvas and that the original texture color is
         // preserved in pixels that aren't rendered to via the surface.
         // This works only for non-multisampled case.
-        GrBackendTexture backendTex;
-        auto surface = surfaceFunc(context, 1, kOrigColor, &backendTex);
-        const GrCaps* caps = context->priv().caps();
-        if (!supports_readpixels(caps, surface.get())) {
-            continue;
-        }
-        if (surface) {
+        auto surface = surfaceFunc(context, 1, kOrigColor);
+        if (surface && supports_readpixels(context->priv().caps(), surface.get())) {
             test_surface_draw_partially(reporter, surface, kOrigColor.toSkColor());
-            surface.reset();
-            context->deleteBackendTexture(backendTex);
         }
     }
 }
@@ -935,7 +885,7 @@
     GrGpu* gpu = ctx->priv().getGpu();
 
     for (bool useTexture : {false, true}) {
-        GrBackendTexture backendTex;
+        sk_sp<sk_gpu_test::ManagedBackendTexture> mbet;
         GrBackendRenderTarget backendRT;
         sk_sp<SkSurface> surface;
 
@@ -945,16 +895,22 @@
         if (useTexture) {
             SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
                                                kPremul_SkAlphaType);
-            if (!CreateBackendTexture(ctx, &backendTex, ii, SkColors::kRed, GrMipmapped::kNo,
-                                      GrRenderable::kYes)) {
+            mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(ctx, ii, GrMipMapped::kNo,
+                                                                    GrRenderable::kYes);
+            if (!mbet) {
                 continue;
             }
 
-            surface = SkSurface::MakeFromBackendTexture(ctx, backendTex, texOrigin, 1,
-                                                        kRGBA_8888_SkColorType,
-                                                        nullptr, nullptr,
-                                                        ReleaseChecker::Release,
-                                                        &releaseChecker);
+            surface = SkSurface::MakeFromBackendTexture(
+                    ctx,
+                    mbet->texture(),
+                    texOrigin,
+                    /*sample count*/ 1,
+                    kRGBA_8888_SkColorType,
+                    /*color space*/ nullptr,
+                    /*surface props*/ nullptr,
+                    sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+                    mbet->releaseContext(ReleaseChecker::Release, &releaseChecker));
         } else {
             backendRT = gpu->createTestingOnlyBackendRenderTarget({kWidth, kHeight},
                                                                   GrColorType::kRGBA_8888);
@@ -981,9 +937,7 @@
         surface.reset(nullptr); // force a release of the surface
         REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
 
-        if (useTexture) {
-            DeleteBackendTexture(ctx, backendTex);
-        } else {
+        if (!useTexture) {
             gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
         }
     }
@@ -1004,8 +958,7 @@
     for (auto& surfaceFunc :
          {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
         for (int sampleCnt : {1, 4, 8}) {
-            GrBackendTexture backendTex;
-            auto surface = surfaceFunc(context, sampleCnt, kOrigColor, &backendTex);
+            auto surface = surfaceFunc(context, sampleCnt, kOrigColor);
 
             if (!surface && sampleCnt > 1) {
                 // Certain platforms don't support MSAA, skip these.
@@ -1017,9 +970,6 @@
             GrRenderTarget* rt = surface->getCanvas()
                 ->internal_private_accessTopLayerRenderTargetContext()->accessRenderTarget();
             REPORTER_ASSERT(reporter, resourceProvider->attachStencilAttachment(rt, sampleCnt));
-            if (backendTex.isValid()) {
-                context->deleteBackendTexture(backendTex);
-            }
         }
     }
 }
@@ -1028,34 +978,29 @@
     auto context = ctxInfo.directContext();
 
     for (int sampleCnt : {1, 2}) {
-        GrBackendTexture backendTexture1;
         auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
-        if (!CreateBackendTexture(context, &backendTexture1, ii, SkColors::kTransparent,
-                                  GrMipmapped::kNo, GrRenderable::kYes)) {
+        auto mbet1 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
+                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
+        if (!mbet1) {
             continue;
         }
-        SkScopeExit delete1(
-                [context, &backendTexture1] { DeleteBackendTexture(context, backendTexture1); });
-        GrBackendTexture backendTexture2;
-        if (!CreateBackendTexture(context, &backendTexture2, ii, SkColors::kTransparent,
-                                  GrMipmapped::kNo, GrRenderable::kYes)) {
+        auto mbet2 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
+                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
+        if (!mbet2) {
             ERRORF(reporter, "Expected to be able to make second texture");
             continue;
         }
-        SkScopeExit delete2(
-                [context, &backendTexture2] { DeleteBackendTexture(context, backendTexture2); });
         auto ii2 = ii.makeWH(8, 8);
+        auto mbet3 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
+                context, ii2, GrMipmapped::kNo, GrRenderable::kYes);
         GrBackendTexture backendTexture3;
-        if (!CreateBackendTexture(context, &backendTexture3, ii2, SkColors::kTransparent,
-                                  GrMipmapped::kNo, GrRenderable::kYes)) {
+        if (!mbet3) {
             ERRORF(reporter, "Couldn't create different sized texture.");
             continue;
         }
-        SkScopeExit delete3(
-                [context, &backendTexture3] { DeleteBackendTexture(context, backendTexture3); });
 
         auto surf = SkSurface::MakeFromBackendTexture(
-                context, backendTexture1, kTopLeft_GrSurfaceOrigin, sampleCnt,
+                context, mbet1->texture(), kTopLeft_GrSurfaceOrigin, sampleCnt,
                 kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
         if (!surf) {
             continue;
@@ -1066,7 +1011,7 @@
         surf->getCanvas()->saveLayer(nullptr, nullptr);
         surf->getCanvas()->clipRect(SkRect::MakeXYWH(0, 0, 1, 1));
         // switch origin while we're at it.
-        bool replaced = surf->replaceBackendTexture(backendTexture2, kBottomLeft_GrSurfaceOrigin);
+        bool replaced = surf->replaceBackendTexture(mbet2->texture(), kBottomLeft_GrSurfaceOrigin);
         REPORTER_ASSERT(reporter, replaced);
         SkPaint paint;
         paint.setColor(SK_ColorRED);
@@ -1091,7 +1036,7 @@
         }
         // The original texture should still be all blue.
         surf = SkSurface::MakeFromBackendTexture(
-                context, backendTexture1, kBottomLeft_GrSurfaceOrigin, sampleCnt,
+                context, mbet1->texture(), kBottomLeft_GrSurfaceOrigin, sampleCnt,
                 kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
         if (!surf) {
             ERRORF(reporter, "Could not create second surface.");
@@ -1113,17 +1058,17 @@
 
         // Can't replace with the same texture
         REPORTER_ASSERT(reporter,
-                        !surf->replaceBackendTexture(backendTexture1, kTopLeft_GrSurfaceOrigin));
+                        !surf->replaceBackendTexture(mbet1->texture(), kTopLeft_GrSurfaceOrigin));
         // Can't replace with invalid texture
         REPORTER_ASSERT(reporter, !surf->replaceBackendTexture({}, kTopLeft_GrSurfaceOrigin));
         // Can't replace with different size texture.
         REPORTER_ASSERT(reporter,
-                        !surf->replaceBackendTexture(backendTexture3, kTopLeft_GrSurfaceOrigin));
+                        !surf->replaceBackendTexture(mbet3->texture(), kTopLeft_GrSurfaceOrigin));
         // Can't replace texture of non-wrapped SkSurface.
         surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, sampleCnt, nullptr);
         REPORTER_ASSERT(reporter, surf);
         if (surf) {
-            REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(backendTexture1,
+            REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(mbet1->texture(),
                                                                    kTopLeft_GrSurfaceOrigin));
         }
     }
diff --git a/tests/TestUtils.cpp b/tests/TestUtils.cpp
index 3499376..6c01b4f 100644
--- a/tests/TestUtils.cpp
+++ b/tests/TestUtils.cpp
@@ -107,68 +107,6 @@
     }
 }
 
-bool CreateBackendTexture(GrDirectContext* dContext,
-                          GrBackendTexture* backendTex,
-                          int width, int height,
-                          SkColorType colorType,
-                          const SkColor4f& color,
-                          GrMipmapped mipMapped,
-                          GrRenderable renderable,
-                          GrProtected isProtected) {
-    SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
-    return CreateBackendTexture(dContext, backendTex, info, color, mipMapped, renderable,
-                                isProtected);
-}
-
-bool CreateBackendTexture(GrDirectContext* dContext,
-                          GrBackendTexture* backendTex,
-                          const SkImageInfo& ii,
-                          const SkColor4f& color,
-                          GrMipmapped mipMapped,
-                          GrRenderable renderable,
-                          GrProtected isProtected) {
-    bool finishedBECreate = false;
-    auto markFinished = [](void* context) {
-        *(bool*)context = true;
-    };
-
-    *backendTex = dContext->createBackendTexture(ii.width(), ii.height(), ii.colorType(),
-                                                 color, mipMapped, renderable, isProtected,
-                                                 markFinished, &finishedBECreate);
-    if (backendTex->isValid()) {
-        dContext->submit();
-        while (!finishedBECreate) {
-            dContext->checkAsyncWorkCompletion();
-        }
-    }
-    return backendTex->isValid();
-}
-
-bool CreateBackendTexture(GrDirectContext* dContext,
-                          GrBackendTexture* backendTex,
-                          const SkBitmap& bm) {
-    bool finishedBECreate = false;
-    auto markFinished = [](void* context) {
-        *(bool*)context = true;
-    };
-
-    *backendTex = dContext->createBackendTexture(bm.pixmap(), GrRenderable::kNo, GrProtected::kNo,
-                                                 markFinished, &finishedBECreate);
-    if (backendTex->isValid()) {
-        dContext->submit();
-        while (!finishedBECreate) {
-            dContext->checkAsyncWorkCompletion();
-        }
-    }
-    return backendTex->isValid();
-}
-
-void DeleteBackendTexture(GrDirectContext* dContext, const GrBackendTexture& backendTex) {
-    dContext->flush();
-    dContext->submit(true);
-    dContext->deleteBackendTexture(backendTex);
-}
-
 bool DoesFullBufferContainCorrectColor(const GrColor* srcBuffer,
                                        const GrColor* dstBuffer,
                                        int width, int height) {
diff --git a/tests/TestUtils.h b/tests/TestUtils.h
index d8e7abd..c5964b0 100644
--- a/tests/TestUtils.h
+++ b/tests/TestUtils.h
@@ -34,30 +34,6 @@
 // Fills data with a red-green gradient
 void FillPixelData(int width, int height, GrColor* data);
 
-// Create a solid colored backend texture and syncs the CPU to wait for upload to finish
-bool CreateBackendTexture(GrDirectContext*,
-                          GrBackendTexture* backendTex,
-                          int width, int height,
-                          SkColorType colorType,
-                          const SkColor4f& color,
-                          GrMipmapped,
-                          GrRenderable,
-                          GrProtected = GrProtected::kNo);
-
-bool CreateBackendTexture(GrDirectContext*,
-                          GrBackendTexture* backendTex,
-                          const SkImageInfo& ii,
-                          const SkColor4f& color,
-                          GrMipmapped,
-                          GrRenderable,
-                          GrProtected = GrProtected::kNo);
-
-bool CreateBackendTexture(GrDirectContext*,
-                          GrBackendTexture* backendTex,
-                          const SkBitmap& bm);
-
-void DeleteBackendTexture(GrDirectContext*, const GrBackendTexture& backendTex);
-
 // Checks srcBuffer and dstBuffer contain the same colors
 bool DoesFullBufferContainCorrectColor(const GrColor* srcBuffer,
                                        const GrColor* dstBuffer,
diff --git a/tests/TextureProxyTest.cpp b/tests/TextureProxyTest.cpp
index fe2a0cd..dff9e52 100644
--- a/tests/TextureProxyTest.cpp
+++ b/tests/TextureProxyTest.cpp
@@ -9,6 +9,7 @@
 
 #include "tests/Test.h"
 
+#include "include/core/SkImage.h"
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrDirectContext.h"
 #include "src/gpu/GrContextPriv.h"
@@ -18,9 +19,8 @@
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrTexture.h"
 #include "src/gpu/GrTextureProxy.h"
-
-#include "include/core/SkImage.h"
 #include "src/gpu/SkGr.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 #ifdef SK_DAWN
 #include "src/gpu/dawn/GrDawnGpu.h"
@@ -96,29 +96,26 @@
     return proxy;
 }
 
-static sk_sp<GrTextureProxy> create_wrapped_backend(GrDirectContext* dContext,
-                                                    SkBackingFit fit,
-                                                    sk_sp<GrTexture>* backingSurface) {
-    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
-    GrResourceProvider* resourceProvider = dContext->priv().resourceProvider();
-
-    GrBackendFormat format =
-            proxyProvider->caps()->getDefaultBackendFormat(kColorType, GrRenderable::kYes);
-
-    *backingSurface =
-            resourceProvider->createTexture(kSize, format, GrRenderable::kNo, 1, GrMipmapped::kNo,
-                                            SkBudgeted::kNo, GrProtected::kNo);
-    if (!(*backingSurface)) {
+static sk_sp<GrTextureProxy> create_wrapped_backend(GrDirectContext* dContext) {
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext,
+            kSize.width(),
+            kSize.height(),
+            GrColorTypeToSkColorType(kColorType),
+            GrMipmapped::kNo,
+            GrRenderable::kNo,
+            GrProtected::kNo);
+    if (!mbet) {
         return nullptr;
     }
-
-    GrBackendTexture backendTex = (*backingSurface)->getBackendTexture();
-
-    return proxyProvider->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership,
-                                             GrWrapCacheable::kYes, kRead_GrIOType);
+    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
+    return proxyProvider->wrapBackendTexture(mbet->texture(),
+                                             kBorrow_GrWrapOwnership,
+                                             GrWrapCacheable::kYes,
+                                             kRead_GrIOType,
+                                             mbet->refCountedCallback());
 }
 
-
 // This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
 // and looking them up work, etc.
 static void basic_test(GrDirectContext* dContext,
@@ -338,14 +335,11 @@
         }
 
         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
-        sk_sp<GrTexture> backingTex;
-        sk_sp<GrTextureProxy> proxy = create_wrapped_backend(direct, fit, &backingTex);
-        basic_test(direct, reporter, std::move(proxy));
-
-        backingTex = nullptr;
         cache->purgeAllUnlocked();
     }
 
+    basic_test(direct, reporter, create_wrapped_backend(direct));
+
     invalidation_test(direct, reporter);
     invalidation_and_instantiation_test(direct, reporter);
 }
diff --git a/tests/VkBackendSurfaceTest.cpp b/tests/VkBackendSurfaceTest.cpp
index dc61c39..b9f2847 100644
--- a/tests/VkBackendSurfaceTest.cpp
+++ b/tests/VkBackendSurfaceTest.cpp
@@ -11,15 +11,11 @@
 
 #if defined(SK_VULKAN)
 
-#include "include/gpu/vk/GrVkVulkan.h"
-
-#include "tests/Test.h"
-#include "tests/TestUtils.h"
-
 #include "include/core/SkImage.h"
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrDirectContext.h"
 #include "include/gpu/vk/GrVkTypes.h"
+#include "include/gpu/vk/GrVkVulkan.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrTexture.h"
 #include "src/gpu/GrTextureProxy.h"
@@ -30,41 +26,50 @@
 #include "src/image/SkImage_Base.h"
 #include "src/image/SkImage_GpuBase.h"
 #include "src/image/SkSurface_Gpu.h"
+#include "tests/Test.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkImageLayoutTest, reporter, ctxInfo) {
     auto dContext = ctxInfo.directContext();
 
-    GrBackendTexture backendTex;
-    CreateBackendTexture(dContext, &backendTex, 1, 1, kRGBA_8888_SkColorType,
-                         SkColors::kTransparent, GrMipmapped::kNo,
-                         GrRenderable::kNo, GrProtected::kNo);
-    REPORTER_ASSERT(reporter, backendTex.isValid());
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext, 1, 1, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo);
+    if (!mbet) {
+        ERRORF(reporter, "Could not create backend texture.");
+        return;
+    }
 
     GrVkImageInfo info;
-    REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, mbet->texture().getVkImageInfo(&info));
     VkImageLayout initLayout = info.fImageLayout;
 
     // Verify that setting that layout via a copy of a backendTexture is reflected in all the
     // backendTextures.
-    GrBackendTexture backendTexCopy = backendTex;
-    REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info));
+    GrBackendTexture backendTex1 = mbet->texture();
+    GrBackendTexture backendTex2 = backendTex1;
+    REPORTER_ASSERT(reporter, backendTex2.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
 
-    backendTexCopy.setVkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+    backendTex2.setVkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 
-    REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, backendTex1.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
 
-    REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, backendTex2.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
 
     // Setting back the layout since we didn't actually change it
-    backendTex.setVkImageLayout(initLayout);
+    backendTex1.setVkImageLayout(initLayout);
 
-    sk_sp<SkImage> wrappedImage = SkImage::MakeFromTexture(dContext, backendTex,
-                                                           kTopLeft_GrSurfaceOrigin,
-                                                           kRGBA_8888_SkColorType,
-                                                           kPremul_SkAlphaType, nullptr);
+    sk_sp<SkImage> wrappedImage = SkImage::MakeFromTexture(
+            dContext,
+            backendTex1,
+            kTopLeft_GrSurfaceOrigin,
+            kRGBA_8888_SkColorType,
+            kPremul_SkAlphaType,
+            /*color space*/ nullptr,
+            sk_gpu_test::ManagedBackendTexture::ReleaseProc,
+            mbet->releaseContext());
     REPORTER_ASSERT(reporter, wrappedImage.get());
 
     const GrSurfaceProxyView* view = as_IB(wrappedImage)->view(dContext);
@@ -78,7 +83,7 @@
     REPORTER_ASSERT(reporter, initLayout == vkTexture->currentLayout());
     vkTexture->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
 
-    REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, backendTex1.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == info.fImageLayout);
 
     GrBackendTexture backendTexImage = wrappedImage->getBackendTexture(false);
@@ -91,10 +96,10 @@
 
     vkTexture->updateImageLayout(initLayout);
 
-    REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, backendTex1.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
 
-    REPORTER_ASSERT(reporter, backendTexCopy.getVkImageInfo(&info));
+    REPORTER_ASSERT(reporter, backendTex2.getVkImageInfo(&info));
     REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
 
     REPORTER_ASSERT(reporter, backendTexImage.getVkImageInfo(&info));
@@ -103,25 +108,23 @@
     // Check that we can do things like assigning the backend texture to invalid one, assign an
     // invalid one, assin a backend texture to inself etc. Success here is that we don't hit any of
     // our ref counting asserts.
-    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTexCopy));
+    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex1, backendTex2));
 
     GrBackendTexture invalidTexture;
     REPORTER_ASSERT(reporter, !invalidTexture.isValid());
-    REPORTER_ASSERT(reporter, !GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTexCopy));
+    REPORTER_ASSERT(reporter, !GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTex2));
 
-    backendTexCopy = invalidTexture;
-    REPORTER_ASSERT(reporter, !backendTexCopy.isValid());
-    REPORTER_ASSERT(reporter, !GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTexCopy));
+    backendTex2 = invalidTexture;
+    REPORTER_ASSERT(reporter, !backendTex2.isValid());
+    REPORTER_ASSERT(reporter, !GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTex2));
 
-    invalidTexture = backendTex;
+    invalidTexture = backendTex1;
     REPORTER_ASSERT(reporter, invalidTexture.isValid());
-    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTex));
+    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(invalidTexture, backendTex1));
 
     invalidTexture = static_cast<decltype(invalidTexture)&>(invalidTexture);
     REPORTER_ASSERT(reporter, invalidTexture.isValid());
     REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(invalidTexture, invalidTexture));
-
-    dContext->deleteBackendTexture(backendTex);
 }
 
 // This test is disabled because it executes illegal vulkan calls which cause the validations layers
diff --git a/tests/VkWrapTests.cpp b/tests/VkWrapTests.cpp
index 17a1c02..7f163f8 100644
--- a/tests/VkWrapTests.cpp
+++ b/tests/VkWrapTests.cpp
@@ -11,21 +11,19 @@
 
 #if defined(SK_VULKAN)
 
-#include "include/gpu/vk/GrVkVulkan.h"
-
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrDirectContext.h"
+#include "include/gpu/vk/GrVkTypes.h"
+#include "include/gpu/vk/GrVkVulkan.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrRenderTarget.h"
 #include "src/gpu/GrTexture.h"
-#include "tools/gpu/GrContextFactory.h"
-
-#include "include/gpu/vk/GrVkTypes.h"
 #include "src/gpu/vk/GrVkCaps.h"
 #include "src/gpu/vk/GrVkGpu.h"
 #include "src/gpu/vk/GrVkMemory.h"
 #include "tests/Test.h"
-#include "tests/TestUtils.h"
+#include "tools/gpu/GrContextFactory.h"
+#include "tools/gpu/ManagedBackendTexture.h"
 
 using sk_gpu_test::GrContextFactory;
 
@@ -34,30 +32,36 @@
 const SkColorType kColorType = SkColorType::kRGBA_8888_SkColorType;
 
 void wrap_tex_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
-
     GrGpu* gpu = dContext->priv().getGpu();
 
-    GrBackendTexture origBackendTex;
-    CreateBackendTexture(dContext, &origBackendTex, kW, kH, kColorType, SkColors::kTransparent,
-                         GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext, kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo);
+    if (!mbet) {
+        ERRORF(reporter, "Could not create backend texture.");
+        return;
+    }
+
+    GrBackendTexture origBackendTex = mbet->texture();
 
     GrVkImageInfo imageInfo;
     SkAssertResult(origBackendTex.getVkImageInfo(&imageInfo));
 
-    sk_sp<GrTexture> tex = gpu->wrapBackendTexture(origBackendTex, kBorrow_GrWrapOwnership,
-                                                   GrWrapCacheable::kNo, kRead_GrIOType);
-    REPORTER_ASSERT(reporter, tex);
+    {
+        sk_sp<GrTexture> tex = gpu->wrapBackendTexture(origBackendTex, kBorrow_GrWrapOwnership,
+                                                       GrWrapCacheable::kNo, kRead_GrIOType);
+        REPORTER_ASSERT(reporter, tex);
+    }
 
     // image is null
     {
         GrVkImageInfo backendCopy = imageInfo;
         backendCopy.fImage = VK_NULL_HANDLE;
         GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
-        tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
+        sk_sp<GrTexture> tex = gpu->wrapBackendTexture(
+                backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
         REPORTER_ASSERT(reporter, !tex);
-        tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
+        tex = gpu->wrapBackendTexture(
+                backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
         REPORTER_ASSERT(reporter, !tex);
     }
 
@@ -66,11 +70,11 @@
         GrVkImageInfo backendCopy = imageInfo;
         backendCopy.fAlloc = GrVkAlloc();
         GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
-        tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
+        sk_sp<GrTexture> tex = gpu->wrapBackendTexture(
+                backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
         REPORTER_ASSERT(reporter, tex);
-        tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
+        tex = gpu->wrapBackendTexture(
+                backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
         REPORTER_ASSERT(reporter, !tex);
     }
 
@@ -78,84 +82,71 @@
     {
         GrVkImageInfo backendCopy = imageInfo;
         GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
-        tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
+        sk_sp<GrTexture> tex = gpu->wrapBackendTexture(
+                backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
 
         REPORTER_ASSERT(reporter, tex);
-    }
-
-    // image has MSAA
-    {
-        GrVkImageInfo backendCopy = imageInfo;
-        backendCopy.fSampleCount = 4;
-        GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
-        tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
-        REPORTER_ASSERT(reporter, !tex);
-        tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
-                                      kRead_GrIOType);
-        REPORTER_ASSERT(reporter, !tex);
+        if (tex) {
+            mbet->wasAdopted();
+        }
     }
 }
 
 void wrap_rt_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
     GrGpu* gpu = dContext->priv().getGpu();
+    GrColorType ct = SkColorTypeToGrColorType(kColorType);
 
-    GrBackendTexture origBackendTex;
-    CreateBackendTexture(dContext, &origBackendTex, kW, kH, kColorType, SkColors::kTransparent,
-                         GrMipmapped::kNo, GrRenderable::kYes, GrProtected::kNo);
+    for (int sampleCnt : {1, 4}) {
+        GrBackendFormat format = gpu->caps()->getDefaultBackendFormat(ct, GrRenderable::kYes);
+        if (sampleCnt > gpu->caps()->maxRenderTargetSampleCount(format)) {
+            continue;
+        }
 
-    GrVkImageInfo imageInfo;
-    SkAssertResult(origBackendTex.getVkImageInfo(&imageInfo));
+        GrBackendRenderTarget origBackendRT =
+                gpu->createTestingOnlyBackendRenderTarget({kW, kH}, ct, sampleCnt);
+        if (!origBackendRT.isValid()) {
+            ERRORF(reporter, "Could not create backend render target.");
+        }
 
-    GrBackendRenderTarget origBackendRT(kW, kH, 1, imageInfo);
+        GrVkImageInfo imageInfo;
+        REPORTER_ASSERT(reporter, origBackendRT.getVkImageInfo(&imageInfo));
 
-    sk_sp<GrRenderTarget> rt = gpu->wrapBackendRenderTarget(origBackendRT);
-    REPORTER_ASSERT(reporter, rt);
-
-    // image is null
-    {
-        GrVkImageInfo backendCopy = imageInfo;
-        backendCopy.fImage = VK_NULL_HANDLE;
-        GrBackendRenderTarget backendRT(kW, kH, 1, backendCopy);
-        rt = gpu->wrapBackendRenderTarget(backendRT);
-        REPORTER_ASSERT(reporter, !rt);
-    }
-
-    // alloc is null
-    {
-        GrVkImageInfo backendCopy = imageInfo;
-        backendCopy.fAlloc = GrVkAlloc();
-        // can wrap null alloc
-        GrBackendRenderTarget backendRT(kW, kH, 1, backendCopy);
-        rt = gpu->wrapBackendRenderTarget(backendRT);
+        sk_sp<GrRenderTarget> rt = gpu->wrapBackendRenderTarget(origBackendRT);
         REPORTER_ASSERT(reporter, rt);
-    }
 
-    // Image has MSAA
-    {
-        GrColorType ct = SkColorTypeToGrColorType(kColorType);
-        GrGpu* gpu = dContext->priv().getGpu();
-        GrBackendRenderTarget backendRT =
-                gpu->createTestingOnlyBackendRenderTarget({kW, kW}, ct, 4);
-        if (backendRT.isValid()) {
+        // image is null
+        {
+            GrVkImageInfo backendCopy = imageInfo;
+            backendCopy.fImage = VK_NULL_HANDLE;
+            GrBackendRenderTarget backendRT(kW, kH, 1, backendCopy);
+            rt = gpu->wrapBackendRenderTarget(backendRT);
+            REPORTER_ASSERT(reporter, !rt);
+        }
+
+        // alloc is null
+        {
+            GrVkImageInfo backendCopy = imageInfo;
+            backendCopy.fAlloc = GrVkAlloc();
+            // can wrap null alloc
+            GrBackendRenderTarget backendRT(kW, kH, 1, backendCopy);
             rt = gpu->wrapBackendRenderTarget(backendRT);
             REPORTER_ASSERT(reporter, rt);
-            dContext->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
         }
-    }
 
-    // When we wrapBackendRenderTarget it is always borrowed, so we must make sure to free the
-    // resource when we're done.
-    dContext->deleteBackendTexture(origBackendTex);
+        gpu->deleteTestingOnlyBackendRenderTarget(origBackendRT);
+    }
 }
 
 void wrap_trt_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
     GrGpu* gpu = dContext->priv().getGpu();
 
-    GrBackendTexture origBackendTex;
-    CreateBackendTexture(dContext, &origBackendTex, kW, kH, kColorType, SkColors::kTransparent,
-                         GrMipmapped::kNo, GrRenderable::kYes, GrProtected::kNo);
+    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
+            dContext, kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kYes);
+    if (!mbet) {
+        ERRORF(reporter, "Could not create renderable backend texture.");
+        return;
+    }
+    GrBackendTexture origBackendTex = mbet->texture();
 
     GrVkImageInfo imageInfo;
     SkAssertResult(origBackendTex.getVkImageInfo(&imageInfo));
@@ -190,15 +181,6 @@
         REPORTER_ASSERT(reporter, !tex);
     }
 
-    // check adopt creation
-    {
-        GrVkImageInfo backendCopy = imageInfo;
-        GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
-        tex = gpu->wrapRenderableBackendTexture(backendTex, 1, kAdopt_GrWrapOwnership,
-                                                GrWrapCacheable::kNo);
-        REPORTER_ASSERT(reporter, tex);
-    }
-
     // check rendering with MSAA
     {
         int maxSamples = dContext->priv().caps()->maxRenderTargetSampleCount(
@@ -209,14 +191,16 @@
         REPORTER_ASSERT(reporter, SkToBool(tex) == shouldSucceed);
     }
 
-    // Image has MSAA
+    // check adopt creation
     {
         GrVkImageInfo backendCopy = imageInfo;
-        backendCopy.fSampleCount = 4;
         GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
         tex = gpu->wrapRenderableBackendTexture(backendTex, 1, kAdopt_GrWrapOwnership,
                                                 GrWrapCacheable::kNo);
-        REPORTER_ASSERT(reporter, !tex);
+        REPORTER_ASSERT(reporter, tex);
+        if (tex) {
+            mbet->wasAdopted();
+        }
     }
 }
 
diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp
index 6e1c4b0..a18279f 100644
--- a/tools/fm/fm.cpp
+++ b/tools/fm/fm.cpp
@@ -323,11 +323,9 @@
 
         case SurfaceType::kBackendTexture:
             surface = sk_gpu_test::MakeBackendTextureSurface(context,
-                                                             info.dimensions(),
+                                                             info,
                                                              kTopLeft_GrSurfaceOrigin,
                                                              FLAGS_samples,
-                                                             info.colorType(),
-                                                             info.refColorSpace(),
                                                              GrMipmapped::kNo,
                                                              GrProtected::kNo,
                                                              &props);
@@ -335,11 +333,9 @@
 
         case SurfaceType::kBackendRenderTarget:
             surface = sk_gpu_test::MakeBackendRenderTargetSurface(context,
-                                                                  info.dimensions(),
+                                                                  info,
                                                                   kBottomLeft_GrSurfaceOrigin,
                                                                   FLAGS_samples,
-                                                                  info.colorType(),
-                                                                  info.refColorSpace(),
                                                                   GrProtected::kNo,
                                                                   &props);
             break;
diff --git a/tools/gpu/BackendSurfaceFactory.cpp b/tools/gpu/BackendSurfaceFactory.cpp
index 32a6500..2c24760 100644
--- a/tools/gpu/BackendSurfaceFactory.cpp
+++ b/tools/gpu/BackendSurfaceFactory.cpp
@@ -15,7 +15,38 @@
 
 namespace sk_gpu_test {
 
-sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext* context,
+sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext* dContext,
+                                           const SkImageInfo& ii,
+                                           GrSurfaceOrigin origin,
+                                           int sampleCnt,
+                                           GrMipmapped mipMapped,
+                                           GrProtected isProtected,
+                                           const SkSurfaceProps* props) {
+    if (ii.alphaType() == kUnpremul_SkAlphaType) {
+        return nullptr;
+    }
+    auto mbet = ManagedBackendTexture::MakeWithoutData(dContext,
+                                                       ii.width(),
+                                                       ii.height(),
+                                                       ii.colorType(),
+                                                       mipMapped,
+                                                       GrRenderable::kYes,
+                                                       isProtected);
+    if (!mbet) {
+        return nullptr;
+    }
+    return SkSurface::MakeFromBackendTexture(dContext,
+                                             mbet->texture(),
+                                             origin,
+                                             sampleCnt,
+                                             ii.colorType(),
+                                             ii.refColorSpace(),
+                                             props,
+                                             ManagedBackendTexture::ReleaseProc,
+                                             mbet->releaseContext());
+}
+
+sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext* dContext,
                                            SkISize dimensions,
                                            GrSurfaceOrigin origin,
                                            int sampleCnt,
@@ -24,45 +55,29 @@
                                            GrMipmapped mipMapped,
                                            GrProtected isProtected,
                                            const SkSurfaceProps* props) {
-    auto mbet = ManagedBackendTexture::MakeWithoutData(context,
-                                                       dimensions.fWidth,
-                                                       dimensions.fHeight,
-                                                       colorType,
-                                                       mipMapped,
-                                                       GrRenderable::kYes,
-                                                       isProtected);
-    if (!mbet) {
-        return nullptr;
-    }
-    return SkSurface::MakeFromBackendTexture(context,
-                                             mbet->texture(),
-                                             origin,
-                                             sampleCnt,
-                                             colorType,
-                                             std::move(colorSpace),
-                                             props,
-                                             ManagedBackendTexture::ReleaseProc,
-                                             mbet->releaseContext());
+    auto ii = SkImageInfo::Make(dimensions, colorType, kPremul_SkAlphaType, std::move(colorSpace));
+    return MakeBackendTextureSurface(
+            dContext, ii, origin, sampleCnt, mipMapped, isProtected, props);
 }
-
-sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* context,
-                                                SkISize dimensions,
+sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* dContext,
+                                                const SkImageInfo& ii,
                                                 GrSurfaceOrigin origin,
                                                 int sampleCnt,
-                                                SkColorType colorType,
-                                                sk_sp<SkColorSpace> colorSpace,
                                                 GrProtected isProtected,
                                                 const SkSurfaceProps* props) {
-    auto ct = SkColorTypeToGrColorType(colorType);
+    if (ii.alphaType() == kUnpremul_SkAlphaType) {
+        return nullptr;
+    }
+    auto ct = SkColorTypeToGrColorType(ii.colorType());
 
     struct ReleaseContext {
         GrDirectContext* fContext;
         GrBackendRenderTarget fRenderTarget;
     };
 
-    auto bert = context->priv().getGpu()->createTestingOnlyBackendRenderTarget(
-            dimensions, ct, sampleCnt, isProtected);
-    auto rc = new ReleaseContext{context, bert};
+    auto bert = dContext->priv().getGpu()->createTestingOnlyBackendRenderTarget(
+            ii.dimensions(), ct, sampleCnt, isProtected);
+    auto rc = new ReleaseContext{dContext, bert};
     SkASSERT(!bert.isValid() || bert.sampleCnt() >= sampleCnt);
 
     auto proc = [](void* c) {
@@ -74,7 +89,19 @@
     };
 
     return SkSurface::MakeFromBackendRenderTarget(
-            context, bert, origin, colorType, std::move(colorSpace), props, proc, rc);
+            dContext, bert, origin, ii.colorType(), ii.refColorSpace(), props, proc, rc);
+}
+
+sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* dContext,
+                                                SkISize dimensions,
+                                                GrSurfaceOrigin origin,
+                                                int sampleCnt,
+                                                SkColorType colorType,
+                                                sk_sp<SkColorSpace> colorSpace,
+                                                GrProtected isProtected,
+                                                const SkSurfaceProps* props) {
+    auto ii = SkImageInfo::Make(dimensions, colorType, kPremul_SkAlphaType, std::move(colorSpace));
+    return MakeBackendRenderTargetSurface(dContext, ii, origin, sampleCnt, isProtected, props);
 }
 
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/BackendSurfaceFactory.h b/tools/gpu/BackendSurfaceFactory.h
index c0177e7..ca35a47 100644
--- a/tools/gpu/BackendSurfaceFactory.h
+++ b/tools/gpu/BackendSurfaceFactory.h
@@ -20,6 +20,14 @@
 namespace sk_gpu_test {
 
 sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext*,
+                                           const SkImageInfo&,
+                                           GrSurfaceOrigin,
+                                           int sampleCnt,
+                                           GrMipmapped = GrMipmapped::kNo,
+                                           GrProtected = GrProtected::kNo,
+                                           const SkSurfaceProps* = nullptr);
+
+sk_sp<SkSurface> MakeBackendTextureSurface(GrDirectContext*,
                                            SkISize,
                                            GrSurfaceOrigin,
                                            int sampleCnt,
@@ -31,6 +39,13 @@
 
 /** Creates an SkSurface backed by a non-textureable render target. */
 sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext*,
+                                                const SkImageInfo&,
+                                                GrSurfaceOrigin,
+                                                int sampleCnt,
+                                                GrProtected = GrProtected::kNo,
+                                                const SkSurfaceProps* = nullptr);
+
+sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext*,
                                                 SkISize,
                                                 GrSurfaceOrigin,
                                                 int sampleCnt,
diff --git a/tools/gpu/BackendTextureImageFactory.cpp b/tools/gpu/BackendTextureImageFactory.cpp
index b0faf45..e2950af 100644
--- a/tools/gpu/BackendTextureImageFactory.cpp
+++ b/tools/gpu/BackendTextureImageFactory.cpp
@@ -40,4 +40,36 @@
                                     ManagedBackendTexture::ReleaseProc,
                                     mbet->releaseContext());
 }
+
+sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext* dContext,
+                                       const SkImageInfo& info,
+                                       SkColor4f color,
+                                       GrMipmapped mipmapped,
+                                       GrRenderable renderable,
+                                       GrSurfaceOrigin origin) {
+    if (info.alphaType() == kOpaque_SkAlphaType) {
+        color = color.makeOpaque();
+    } else if (info.alphaType() == kPremul_SkAlphaType) {
+        auto pmColor = color.premul();
+        color = {pmColor.fR, pmColor.fG, pmColor.fB, pmColor.fA};
+    }
+    auto mbet = ManagedBackendTexture::MakeWithData(dContext,
+                                                    info.width(),
+                                                    info.height(),
+                                                    info.colorType(),
+                                                    color,
+                                                    mipmapped,
+                                                    renderable,
+                                                    GrProtected::kNo);
+
+    return SkImage::MakeFromTexture(dContext,
+                                    mbet->texture(),
+                                    origin,
+                                    info.colorType(),
+                                    info.alphaType(),
+                                    info.refColorSpace(),
+                                    ManagedBackendTexture::ReleaseProc,
+                                    mbet->releaseContext());
+}
+
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/BackendTextureImageFactory.h b/tools/gpu/BackendTextureImageFactory.h
index 3de31a5..289f268 100644
--- a/tools/gpu/BackendTextureImageFactory.h
+++ b/tools/gpu/BackendTextureImageFactory.h
@@ -5,12 +5,15 @@
  * found in the LICENSE file.
  */
 
+#include "include/core/SkColor.h"
 #include "include/core/SkRefCnt.h"
 #include "include/gpu/GrTypes.h"
 
 class GrDirectContext;
+class SkColorSpace;
 class SkImage;
 class SkPixmap;
+struct SkISize;
 
 namespace sk_gpu_test {
 /**
@@ -20,6 +23,17 @@
  * For testing purposes the texture can be made renderable to exercise different code paths for
  * renderable textures/formats.
  */
-sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext*, const SkPixmap&,
-                                       GrRenderable, GrSurfaceOrigin);
+sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext*,
+                                       const SkPixmap&,
+                                       GrRenderable,
+                                       GrSurfaceOrigin);
+
+/** Creates an image of with a solid color. */
+sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext*,
+                                       const SkImageInfo& info,
+                                       SkColor4f,
+                                       GrMipmapped = GrMipmapped::kNo,
+                                       GrRenderable = GrRenderable::kNo,
+                                       GrSurfaceOrigin = GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin);
+
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/ManagedBackendTexture.cpp b/tools/gpu/ManagedBackendTexture.cpp
index 8409caa..192a57c 100644
--- a/tools/gpu/ManagedBackendTexture.cpp
+++ b/tools/gpu/ManagedBackendTexture.cpp
@@ -7,10 +7,27 @@
 
 #include "tools/gpu/ManagedBackendTexture.h"
 
+#include "include/core/SkImageInfo.h"
+#include "include/private/GrTypesPriv.h"
+#include "src/core/SkMipmap.h"
+
+namespace {
+
+struct Context {
+    sk_sp<sk_gpu_test::ManagedBackendTexture> fMBET;
+    GrGpuFinishedProc fWrappedProc = nullptr;
+    GrGpuFinishedContext fWrappedContext = nullptr;
+};
+
+}  // anonymous namespace
+
 namespace sk_gpu_test {
 
-void ManagedBackendTexture::ReleaseProc(void* context) {
-    static_cast<ManagedBackendTexture*>(context)->unref();
+void ManagedBackendTexture::ReleaseProc(void* ctx) {
+    std::unique_ptr<Context> context(static_cast<Context*>(ctx));
+    if (context->fWrappedProc) {
+        context->fWrappedProc(context->fWrappedContext);
+    }
 }
 
 ManagedBackendTexture::~ManagedBackendTexture() {
@@ -19,9 +36,49 @@
     }
 }
 
-void* ManagedBackendTexture::releaseContext() {
-    this->ref();
-    return static_cast<void*>(this);
+void* ManagedBackendTexture::releaseContext(GrGpuFinishedProc wrappedProc,
+                                            GrGpuFinishedContext wrappedCtx) const {
+    // Make sure we don't get a wrapped ctx without a wrapped proc
+    SkASSERT(!wrappedCtx || wrappedProc);
+    return new Context{sk_ref_sp(this), wrappedProc, wrappedCtx};
+}
+
+sk_sp<GrRefCntedCallback> ManagedBackendTexture::refCountedCallback() const {
+    return sk_make_sp<GrRefCntedCallback>(ReleaseProc, this->releaseContext());
+}
+
+void ManagedBackendTexture::wasAdopted() { fTexture = {}; }
+
+sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromInfo(GrDirectContext* dContext,
+                                                                 const SkImageInfo& ii,
+                                                                 GrMipmapped mipmapped,
+                                                                 GrRenderable renderable,
+                                                                 GrProtected isProtected) {
+    return MakeWithoutData(
+            dContext, ii.width(), ii.height(), ii.colorType(), mipmapped, renderable, isProtected);
+}
+
+sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromBitmap(GrDirectContext* dContext,
+                                                                   const SkBitmap& bitmap,
+                                                                   GrMipmapped mipmapped,
+                                                                   GrRenderable renderable,
+                                                                   GrProtected isProtected) {
+    std::vector<SkPixmap> levels({bitmap.pixmap()});
+    std::unique_ptr<SkMipmap> mm;
+
+    if (mipmapped == GrMipmapped::kYes) {
+        mm.reset(SkMipmap::Build(bitmap, nullptr));
+        if (!mm) {
+            return nullptr;
+        }
+        for (int i = 0; i < mm->countLevels(); ++i) {
+            SkMipmap::Level level;
+            SkAssertResult(mm->getLevel(i, &level));
+            levels.push_back(level.fPixmap);
+        }
+    }
+    return MakeWithData(
+            dContext, levels.data(), static_cast<int>(levels.size()), renderable, isProtected);
 }
 
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/ManagedBackendTexture.h b/tools/gpu/ManagedBackendTexture.h
index cd3b023..931e71b 100644
--- a/tools/gpu/ManagedBackendTexture.h
+++ b/tools/gpu/ManagedBackendTexture.h
@@ -11,6 +11,9 @@
 #include "include/core/SkRefCnt.h"
 #include "include/gpu/GrDirectContext.h"
 
+class GrRefCntedCallback;
+struct SkImageInfo;
+
 namespace sk_gpu_test {
 
 class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
@@ -34,6 +37,19 @@
     template <typename... Args>
     static sk_sp<ManagedBackendTexture> MakeWithoutData(GrDirectContext*, Args&&...);
 
+
+    static sk_sp<ManagedBackendTexture> MakeFromInfo(GrDirectContext* dContext,
+                                                     const SkImageInfo&,
+                                                     GrMipmapped = GrMipmapped::kNo,
+                                                     GrRenderable = GrRenderable::kNo,
+                                                     GrProtected = GrProtected::kNo);
+
+    static sk_sp<ManagedBackendTexture> MakeFromBitmap(GrDirectContext*,
+                                                       const SkBitmap&,
+                                                       GrMipmapped,
+                                                       GrRenderable,
+                                                       GrProtected = GrProtected::kNo);
+
     /** GrGpuFinishedProc or image/surface release proc. */
     static void ReleaseProc(void* context);
 
@@ -41,9 +57,18 @@
 
     /**
      * The context to use with ReleaseProc. This adds a ref so it *must* be balanced by a call to
-     * ReleaseProc.
+     * ReleaseProc. If a wrappedProc is provided then it will be called by ReleaseProc.
      */
-    void* releaseContext();
+    void* releaseContext(GrGpuFinishedProc wrappedProc = nullptr,
+                         GrGpuFinishedContext wrappedContext = nullptr) const;
+
+    sk_sp<GrRefCntedCallback> refCountedCallback() const;
+
+    /**
+     * Call if the underlying GrBackendTexture was adopted by a GrContext. This clears this out the
+     * MBET without deleting the texture.
+     */
+    void wasAdopted();
 
     const GrBackendTexture& texture() { return fTexture; }
 
@@ -52,7 +77,7 @@
     ManagedBackendTexture(const ManagedBackendTexture&) = delete;
     ManagedBackendTexture(ManagedBackendTexture&&) = delete;
 
-    GrDirectContext* fDContext = nullptr;
+    sk_sp<GrDirectContext> fDContext;
     GrBackendTexture fTexture;
 };
 
@@ -60,7 +85,7 @@
 inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithData(GrDirectContext* dContext,
                                                                         Args&&... args) {
     sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
-    mbet->fDContext = dContext;
+    mbet->fDContext = sk_ref_sp(dContext);
     mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...,
                                                     ReleaseProc,
                                                     mbet->releaseContext());
@@ -72,7 +97,7 @@
         GrDirectContext* dContext,
         Args&&... args) {
     sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
-    mbet->fDContext = dContext;
+    mbet->fDContext = sk_ref_sp(dContext);
     mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...);
     return mbet;
 }
diff --git a/tools/gpu/vk/VkTestHelper.cpp b/tools/gpu/vk/VkTestHelper.cpp
index 57dc666..12c6807 100644
--- a/tools/gpu/vk/VkTestHelper.cpp
+++ b/tools/gpu/vk/VkTestHelper.cpp
@@ -86,6 +86,12 @@
 }
 
 void VkTestHelper::cleanup() {
+    // Make sure any work, release procs, etc left on the context are finished with before we start
+    // tearing everything down.
+    if (fDirectContext) {
+        fDirectContext->flushAndSubmit(true);
+    }
+
     fDirectContext.reset();
 
     fBackendContext.fMemoryAllocator.reset();