Move GrProtected off GrSurfaceDesc and pass separately.


Change-Id: If628c13bb0e5aa885e4249a37432ba572e65d920
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228440
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkDeferredDisplayListRecorder.cpp b/src/core/SkDeferredDisplayListRecorder.cpp
index 00b1039..691714c 100644
--- a/src/core/SkDeferredDisplayListRecorder.cpp
+++ b/src/core/SkDeferredDisplayListRecorder.cpp
@@ -141,7 +141,6 @@
     GrSurfaceDesc desc;
     desc.fWidth = fCharacterization.width();
     desc.fHeight = fCharacterization.height();
-    desc.fIsProtected = fCharacterization.isProtected();
     desc.fConfig = config;
     desc.fSampleCnt = fCharacterization.sampleCount();
 
@@ -177,6 +176,7 @@
             optionalTextureInfo,
             SkBackingFit::kExact,
             SkBudgeted::kYes,
+            fCharacterization.isProtected(),
             fCharacterization.vulkanSecondaryCBCompatible());
 
     if (!proxy) {
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index 9008436..ffda554 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -186,7 +186,8 @@
                 return std::move(tex);
             },
             backendFormat, desc, GrRenderable::kNo, fSurfaceOrigin, GrMipMapped::kNo,
-            GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo);
+            GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo,
+            GrProtected::kNo);
 
     return texProxy;
 }
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index a62dfab..4c39d3b 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -193,7 +193,8 @@
                 return {std::move(tex), GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
             },
             format, desc, GrRenderable::kNo, fSurfaceOrigin, mipMapped,
-            GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo);
+            GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo,
+            GrProtected::kNo);
 
     if (!proxy) {
         return nullptr;
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 62ed272..7903589 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -501,7 +501,7 @@
         // to ops), so it can't have any pending IO.
         proxy = proxyProvider->createProxy(format, desc, GrRenderable::kNo,
                                            kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox,
-                                           SkBudgeted::kYes);
+                                           SkBudgeted::kYes, GrProtected::kNo);
 
         auto uploader = skstd::make_unique<GrTDeferredProxyUploader<ClipMaskData>>(reducedClip);
         GrTDeferredProxyUploader<ClipMaskData>* uploaderRaw = uploader.get();
diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp
index eb709f3..7010673 100644
--- a/src/gpu/GrDrawOpAtlas.cpp
+++ b/src/gpu/GrDrawOpAtlas.cpp
@@ -524,7 +524,7 @@
     for (uint32_t i = 0; i < this->maxPages(); ++i) {
         fProxies[i] = proxyProvider->createProxy(fFormat, desc, GrRenderable::kNo,
                                                  kTopLeft_GrSurfaceOrigin, SkBackingFit::kExact,
-                                                 SkBudgeted::kYes);
+                                                 SkBudgeted::kYes, GrProtected::kNo);
         if (!fProxies[i]) {
             return false;
         }
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index ce2c840..8a2ea3b 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -145,8 +145,8 @@
 }
 
 sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, GrRenderable renderable,
-                                      SkBudgeted budgeted, const GrMipLevel texels[],
-                                      int mipLevelCount) {
+                                      SkBudgeted budgeted, GrProtected isProtected,
+                                      const GrMipLevel texels[], int mipLevelCount) {
     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
     if (GrPixelConfigIsCompressed(origDesc.fConfig)) {
         // Call GrGpu::createCompressedTexture.
@@ -177,7 +177,8 @@
     }
 
     this->handleDirtyContext();
-    sk_sp<GrTexture> tex = this->onCreateTexture(desc, renderable, budgeted, texels, mipLevelCount);
+    sk_sp<GrTexture> tex =
+            this->onCreateTexture(desc, renderable, budgeted, isProtected, texels, mipLevelCount);
     if (tex) {
         if (!this->caps()->reuseScratchTextures() && renderable == GrRenderable::kNo) {
             tex->resourcePriv().removeScratchKey();
@@ -193,8 +194,8 @@
 }
 
 sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc, GrRenderable renderable,
-                                      SkBudgeted budgeted) {
-    return this->createTexture(desc, renderable, budgeted, nullptr, 0);
+                                      SkBudgeted budgeted, GrProtected isProtected) {
+    return this->createTexture(desc, renderable, budgeted, isProtected, nullptr, 0);
 }
 
 sk_sp<GrTexture> GrGpu::createCompressedTexture(int width, int height,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 27a1941..c870799 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -88,6 +88,7 @@
      * @param desc           describes the texture to be created.
      * @param renderable     should the resulting texture be renderable
      * @param budgeted       does this texture count against the resource cache budget?
+     * @param isProtected    should the texture be created as protected.
      * @param texels         array of mipmap levels containing texel data to load.
      *                       If level i has pixels then it is assumed that its dimensions are
      *                       max(1, floor(desc.fWidth / 2)) by max(1, floor(desc.fHeight / 2)).
@@ -105,12 +106,13 @@
      * @return  The texture object if successful, otherwise nullptr.
      */
     sk_sp<GrTexture> createTexture(const GrSurfaceDesc& desc, GrRenderable renderable, SkBudgeted,
-                                   const GrMipLevel texels[], int mipLevelCount);
+                                   GrProtected isProtected, const GrMipLevel texels[],
+                                   int mipLevelCount);
 
     /**
      * Simplified createTexture() interface for when there is no initial texel data to upload.
      */
-    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted);
+    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected);
 
     sk_sp<GrTexture> createCompressedTexture(int width, int height, SkImage::CompressionType,
                                              SkBudgeted, const void* data, size_t dataSize);
@@ -526,8 +528,8 @@
     // overridden by backend-specific derived class to create objects.
     // Texture size and sample size will have already been validated in base class before
     // onCreateTexture is called.
-    virtual sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable renderable,
-                                             SkBudgeted, const GrMipLevel texels[],
+    virtual sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted,
+                                             GrProtected, const GrMipLevel[],
                                              int mipLevelCount) = 0;
     virtual sk_sp<GrTexture> onCreateCompressedTexture(int width, int height,
                                                        SkImage::CompressionType, SkBudgeted,
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index 5e0fd0e..d31e3d8 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -116,7 +116,7 @@
 #if GR_TEST_UTILS
 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
         const GrSurfaceDesc& desc, GrRenderable renderable, GrSurfaceOrigin origin,
-        SkBackingFit fit, SkBudgeted budgeted) {
+        SkBackingFit fit, SkBudgeted budgeted, GrProtected isProtected) {
     GrContext* direct = fImageContext->priv().asDirectContext();
     if (!direct) {
         return nullptr;
@@ -126,10 +126,10 @@
     sk_sp<GrTexture> tex;
 
     if (SkBackingFit::kApprox == fit) {
-        tex = resourceProvider->createApproxTexture(desc, renderable,
+        tex = resourceProvider->createApproxTexture(desc, renderable, isProtected,
                                                     GrResourceProvider::Flags::kNoPendingIO);
     } else {
-        tex = resourceProvider->createTexture(desc, renderable, budgeted,
+        tex = resourceProvider->createTexture(desc, renderable, budgeted, isProtected,
                                               GrResourceProvider::Flags::kNoPendingIO);
     }
     if (!tex) {
@@ -257,12 +257,12 @@
                 SkAssertResult(srcImage->peekPixels(&pixMap));
                 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
 
-                return LazyInstantiationResult(
-                        resourceProvider->createTexture(desc, renderable, budgeted, fit, mipLevel,
-                                                        GrResourceProvider::Flags::kNoPendingIO));
+                return LazyInstantiationResult(resourceProvider->createTexture(
+                        desc, renderable, budgeted, fit, GrProtected::kNo, mipLevel,
+                        GrResourceProvider::Flags::kNoPendingIO));
             },
             format, desc, renderable, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, surfaceFlags, fit,
-            budgeted);
+            budgeted, GrProtected::kNo);
 
     if (!proxy) {
         return nullptr;
@@ -288,7 +288,8 @@
                                                          const GrSurfaceDesc& desc,
                                                          GrRenderable renderable,
                                                          GrSurfaceOrigin origin,
-                                                         SkBudgeted budgeted) {
+                                                         SkBudgeted budgeted,
+                                                         GrProtected isProtected) {
     ASSERT_SINGLE_OWNER
 
     if (this->isAbandoned()) {
@@ -296,7 +297,8 @@
     }
 
     return this->createProxy(format, desc, renderable, origin, GrMipMapped::kYes,
-                             SkBackingFit::kExact, budgeted, GrInternalSurfaceFlags::kNone);
+                             SkBackingFit::kExact, budgeted, isProtected,
+                             GrInternalSurfaceFlags::kNone);
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
@@ -386,10 +388,11 @@
                 }
 
                 return LazyInstantiationResult(resourceProvider->createTexture(
-                        desc, GrRenderable::kNo, SkBudgeted::kYes, texels.get(), mipLevelCount));
+                        desc, GrRenderable::kNo, SkBudgeted::kYes, GrProtected::kNo, texels.get(),
+                        mipLevelCount));
             },
             format, desc, GrRenderable::kNo, kTopLeft_GrSurfaceOrigin, GrMipMapped::kYes,
-            SkBackingFit::kExact, SkBudgeted::kYes);
+            SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
 
     if (!proxy) {
         return nullptr;
@@ -438,6 +441,7 @@
                                                    GrMipMapped mipMapped,
                                                    SkBackingFit fit,
                                                    SkBudgeted budgeted,
+                                                   GrProtected isProtected,
                                                    GrInternalSurfaceFlags surfaceFlags) {
     if (GrPixelConfigIsCompressed(desc.fConfig)) {
         // Deferred proxies for compressed textures are not supported.
@@ -475,11 +479,11 @@
         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, format, copyDesc,
                                                                     origin, mipMapped, texSwizzle,
                                                                     outSwizzle, fit, budgeted,
-                                                                    surfaceFlags));
+                                                                    isProtected, surfaceFlags));
     }
 
     return sk_sp<GrTextureProxy>(new GrTextureProxy(format, copyDesc, origin, mipMapped, texSwizzle,
-                                                    fit, budgeted, surfaceFlags));
+                                                    fit, budgeted, isProtected, surfaceFlags));
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
@@ -502,7 +506,7 @@
                         width, height, compressionType, budgeted, data.get()));
             },
             format, desc, GrRenderable::kNo, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
-            SkBackingFit::kExact, SkBudgeted::kYes);
+            SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
 
     if (!proxy) {
         return nullptr;
@@ -736,25 +740,10 @@
                                                        GrSurfaceOrigin origin,
                                                        GrMipMapped mipMapped,
                                                        SkBackingFit fit,
-                                                       SkBudgeted budgeted) {
+                                                       SkBudgeted budgeted,
+                                                       GrProtected isProtected) {
     return this->createLazyProxy(std::move(callback), format, desc, renderable, origin, mipMapped,
-                                 GrInternalSurfaceFlags::kNone, fit, budgeted);
-}
-
-sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
-                                                       const GrBackendFormat& format,
-                                                       const GrSurfaceDesc& desc,
-                                                       GrRenderable renderable,
-                                                       GrSurfaceOrigin origin,
-                                                       GrMipMapped mipMapped,
-                                                       GrInternalSurfaceFlags surfaceFlags,
-                                                       SkBackingFit fit,
-                                                       SkBudgeted budgeted) {
-    // For non-ddl draws always make lazy proxy's single use.
-    LazyInstantiationType lazyType = this->renderingDirectly() ? LazyInstantiationType::kSingleUse
-                                                               : LazyInstantiationType::kMultipleUse;
-    return this->createLazyProxy(std::move(callback), format, desc, renderable, origin, mipMapped,
-                                 surfaceFlags, fit, budgeted, lazyType);
+                                 GrInternalSurfaceFlags::kNone, fit, budgeted, isProtected);
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
@@ -766,6 +755,24 @@
                                                        GrInternalSurfaceFlags surfaceFlags,
                                                        SkBackingFit fit,
                                                        SkBudgeted budgeted,
+                                                       GrProtected isProtected) {
+    // For non-ddl draws always make lazy proxy's single use.
+    LazyInstantiationType lazyType = this->renderingDirectly() ? LazyInstantiationType::kSingleUse
+                                                               : LazyInstantiationType::kMultipleUse;
+    return this->createLazyProxy(std::move(callback), format, desc, renderable, origin, mipMapped,
+                                 surfaceFlags, fit, budgeted, isProtected, lazyType);
+}
+
+sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
+                                                       const GrBackendFormat& format,
+                                                       const GrSurfaceDesc& desc,
+                                                       GrRenderable renderable,
+                                                       GrSurfaceOrigin origin,
+                                                       GrMipMapped mipMapped,
+                                                       GrInternalSurfaceFlags surfaceFlags,
+                                                       SkBackingFit fit,
+                                                       SkBudgeted budgeted,
+                                                       GrProtected isProtected,
                                                        LazyInstantiationType lazyType) {
     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
              (desc.fWidth > 0 && desc.fHeight > 0));
@@ -785,16 +792,17 @@
             renderable == GrRenderable::kYes
                     ? new GrTextureRenderTargetProxy(std::move(callback), lazyType, format, desc,
                                                      origin, mipMapped, texSwizzle, outSwizzle, fit,
-                                                     budgeted, surfaceFlags)
+                                                     budgeted, isProtected, surfaceFlags)
                     : new GrTextureProxy(std::move(callback), lazyType, format, desc, origin,
-                                         mipMapped, texSwizzle, fit, budgeted, surfaceFlags));
+                                         mipMapped, texSwizzle, fit, budgeted, isProtected,
+                                         surfaceFlags));
 }
 
 sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
         LazyInstantiateCallback&& callback, const GrBackendFormat& format,
         const GrSurfaceDesc& desc, GrSurfaceOrigin origin, GrInternalSurfaceFlags surfaceFlags,
         const TextureInfo* textureInfo, SkBackingFit fit, SkBudgeted budgeted,
-        bool wrapsVkSecondaryCB) {
+        GrProtected isProtected, bool wrapsVkSecondaryCB) {
     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
              (desc.fWidth > 0 && desc.fHeight > 0));
 
@@ -820,21 +828,22 @@
         SkASSERT(!wrapsVkSecondaryCB);
         return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
                 std::move(callback), lazyType, format, desc, origin, textureInfo->fMipMapped,
-                texSwizzle, outSwizzle, fit, budgeted, surfaceFlags));
+                texSwizzle, outSwizzle, fit, budgeted, isProtected, surfaceFlags));
     }
 
     GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
             wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes
                                : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo;
 
-    return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
-            std::move(callback), lazyType, format, desc, origin, texSwizzle, outSwizzle, fit,
-            budgeted, surfaceFlags, vkSCB));
+    return sk_sp<GrRenderTargetProxy>(
+            new GrRenderTargetProxy(std::move(callback), lazyType, format, desc, origin, texSwizzle,
+                                    outSwizzle, fit, budgeted, isProtected, surfaceFlags, vkSCB));
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(
         LazyInstantiateCallback&& callback, const GrBackendFormat& format, Renderable renderable,
-        GrSurfaceOrigin origin, GrPixelConfig config, const GrCaps& caps, int sampleCnt) {
+        GrProtected isProtected, GrSurfaceOrigin origin, GrPixelConfig config, const GrCaps& caps,
+        int sampleCnt) {
     SkASSERT(validate_backend_format_and_config(&caps, format, config));
     GrSurfaceDesc desc;
     GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
@@ -852,10 +861,11 @@
                     ? new GrTextureRenderTargetProxy(
                               std::move(callback), LazyInstantiationType::kSingleUse, format, desc,
                               origin, GrMipMapped::kNo, texSwizzle, outSwizzle,
-                              SkBackingFit::kApprox, SkBudgeted::kYes, surfaceFlags)
+                              SkBackingFit::kApprox, SkBudgeted::kYes, isProtected, surfaceFlags)
                     : new GrTextureProxy(std::move(callback), LazyInstantiationType::kSingleUse,
                                          format, desc, origin, GrMipMapped::kNo, texSwizzle,
-                                         SkBackingFit::kApprox, SkBudgeted::kYes, surfaceFlags));
+                                         SkBackingFit::kApprox, SkBudgeted::kYes, isProtected,
+                                         surfaceFlags));
 }
 
 bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index a4b07f9..838eac8 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -73,7 +73,7 @@
      * based on the width and height in the GrSurfaceDesc.
      */
     sk_sp<GrTextureProxy> createMipMapProxy(const GrBackendFormat&, const GrSurfaceDesc&,
-                                            GrRenderable, GrSurfaceOrigin, SkBudgeted);
+                                            GrRenderable, GrSurfaceOrigin, SkBudgeted, GrProtected);
 
     /*
      * Creates a new texture proxy for the bitmap, optionally with mip levels generated by the cpu.
@@ -85,14 +85,14 @@
      */
     sk_sp<GrTextureProxy> createProxy(const GrBackendFormat&, const GrSurfaceDesc&, GrRenderable,
                                       GrSurfaceOrigin, GrMipMapped, SkBackingFit, SkBudgeted,
-                                      GrInternalSurfaceFlags);
+                                      GrProtected, GrInternalSurfaceFlags);
 
     sk_sp<GrTextureProxy> createProxy(
             const GrBackendFormat& format, const GrSurfaceDesc& desc, GrRenderable renderable,
-            GrSurfaceOrigin origin, SkBackingFit fit, SkBudgeted budgeted,
+            GrSurfaceOrigin origin, SkBackingFit fit, SkBudgeted budgeted, GrProtected isProtected,
             GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone) {
         return this->createProxy(format, desc, renderable, origin, GrMipMapped::kNo, fit, budgeted,
-                                 surfaceFlags);
+                                 isProtected, surfaceFlags);
     }
 
     /*
@@ -167,16 +167,16 @@
     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
                                           const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
                                           GrMipMapped, GrInternalSurfaceFlags, SkBackingFit,
-                                          SkBudgeted, LazyInstantiationType);
+                                          SkBudgeted, GrProtected, LazyInstantiationType);
 
     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
                                           const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
                                           GrMipMapped, GrInternalSurfaceFlags, SkBackingFit,
-                                          SkBudgeted);
+                                          SkBudgeted, GrProtected);
 
     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
                                           const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
-                                          GrMipMapped, SkBackingFit, SkBudgeted);
+                                          GrMipMapped, SkBackingFit, SkBudgeted, GrProtected);
 
     /** A null TextureInfo indicates a non-textureable render target. */
     sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
@@ -187,15 +187,17 @@
                                                            const TextureInfo*,
                                                            SkBackingFit,
                                                            SkBudgeted,
+                                                           GrProtected,
                                                            bool wrapsVkSecondaryCB);
 
     /**
      * Fully lazy proxies have unspecified width and height. Methods that rely on those values
      * (e.g., width, height, getBoundsRect) should be avoided.
      */
-    static sk_sp<GrTextureProxy> MakeFullyLazyProxy(
-            LazyInstantiateCallback&&, const GrBackendFormat&, Renderable, GrSurfaceOrigin,
-            GrPixelConfig, const GrCaps&, int sampleCnt = 1);
+    static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&,
+                                                    const GrBackendFormat&, Renderable, GrProtected,
+                                                    GrSurfaceOrigin, GrPixelConfig, const GrCaps&,
+                                                    int sampleCnt = 1);
 
     // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
     // determine if it is going to need a texture domain or a full clear.
@@ -244,7 +246,7 @@
      */
     sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(const GrSurfaceDesc&, GrRenderable,
                                                               GrSurfaceOrigin, SkBackingFit,
-                                                              SkBudgeted);
+                                                              SkBudgeted, GrProtected);
     sk_sp<GrTextureProxy> testingOnly_createWrapped(sk_sp<GrTexture>, GrSurfaceOrigin);
 #endif
 
diff --git a/src/gpu/GrRecordingContext.cpp b/src/gpu/GrRecordingContext.cpp
index 3512e4f..4545ed4 100644
--- a/src/gpu/GrRecordingContext.cpp
+++ b/src/gpu/GrRecordingContext.cpp
@@ -188,16 +188,15 @@
     GrSurfaceDesc desc;
     desc.fWidth = width;
     desc.fHeight = height;
-    desc.fIsProtected = isProtected;
     desc.fConfig = config;
 
     sk_sp<GrTextureProxy> texture;
     if (GrMipMapped::kNo == mipMapped) {
         texture = this->proxyProvider()->createProxy(format, desc, GrRenderable::kNo, origin, fit,
-                                                     budgeted);
+                                                     budgeted, isProtected);
     } else {
         texture = this->proxyProvider()->createMipMapProxy(format, desc, GrRenderable::kNo, origin,
-                                                           budgeted);
+                                                           budgeted, isProtected);
     }
     if (!texture) {
         return nullptr;
@@ -238,17 +237,16 @@
     GrSurfaceDesc desc;
     desc.fWidth = width;
     desc.fHeight = height;
-    desc.fIsProtected = isProtected;
     desc.fConfig = config;
     desc.fSampleCnt = sampleCnt;
 
     sk_sp<GrTextureProxy> rtp;
     if (GrMipMapped::kNo == mipMapped) {
         rtp = this->proxyProvider()->createProxy(format, desc, GrRenderable::kYes, origin, fit,
-                                                 budgeted);
+                                                 budgeted, isProtected);
     } else {
         rtp = this->proxyProvider()->createMipMapProxy(format, desc, GrRenderable::kYes, origin,
-                                                       budgeted);
+                                                       budgeted, isProtected);
     }
     if (!rtp) {
         return nullptr;
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index e26ca65..fcb0b35 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -19,9 +19,9 @@
 #include "src/gpu/GrStencilAttachment.h"
 #include "src/gpu/GrStencilSettings.h"
 
-GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
+GrRenderTarget::GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
                                GrStencilAttachment* stencil)
-        : INHERITED(gpu, desc)
+        : INHERITED(gpu, desc, isProtected)
         , fSampleCnt(desc.fSampleCnt)
         , fSamplePatternKey(GrSamplePatternDictionary::kInvalidSamplePatternKey)
         , fStencilAttachment(stencil) {
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index 0d70920..1d6186d 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -23,9 +23,10 @@
                                          const GrSurfaceDesc& desc, GrSurfaceOrigin origin,
                                          const GrSwizzle& textureSwizzle,
                                          const GrSwizzle& outputSwizzle, SkBackingFit fit,
-                                         SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
+                                         SkBudgeted budgeted, GrProtected isProtected,
+                                         GrInternalSurfaceFlags surfaceFlags)
         : INHERITED(format, desc, GrRenderable::kYes, origin, textureSwizzle, fit, budgeted,
-                    surfaceFlags)
+                    isProtected, surfaceFlags)
         , fSampleCnt(desc.fSampleCnt)
         , fWrapsVkSecondaryCB(WrapsVkSecondaryCB::kNo)
         , fOutputSwizzle(outputSwizzle) {}
@@ -36,10 +37,11 @@
                                          const GrBackendFormat& format, const GrSurfaceDesc& desc,
                                          GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
                                          const GrSwizzle& outputSwizzle, SkBackingFit fit,
-                                         SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags,
+                                         SkBudgeted budgeted, GrProtected isProtected,
+                                         GrInternalSurfaceFlags surfaceFlags,
                                          WrapsVkSecondaryCB wrapsVkSecondaryCB)
         : INHERITED(std::move(callback), lazyType, format, desc, GrRenderable::kYes, origin,
-                    textureSwizzle, fit, budgeted, surfaceFlags)
+                    textureSwizzle, fit, budgeted, isProtected, surfaceFlags)
         , fSampleCnt(desc.fSampleCnt)
         , fWrapsVkSecondaryCB(wrapsVkSecondaryCB)
         , fOutputSwizzle(outputSwizzle) {}
diff --git a/src/gpu/GrRenderTargetProxy.h b/src/gpu/GrRenderTargetProxy.h
index 3faefe6..3e36b6b 100644
--- a/src/gpu/GrRenderTargetProxy.h
+++ b/src/gpu/GrRenderTargetProxy.h
@@ -77,7 +77,7 @@
     // Deferred version
     GrRenderTargetProxy(const GrCaps&, const GrBackendFormat&, const GrSurfaceDesc&,
                         GrSurfaceOrigin, const GrSwizzle& textureSwizzle,
-                        const GrSwizzle& outputSwizzle, SkBackingFit, SkBudgeted,
+                        const GrSwizzle& outputSwizzle, SkBackingFit, SkBudgeted, GrProtected,
                         GrInternalSurfaceFlags);
 
     enum class WrapsVkSecondaryCB : bool { kNo = false, kYes = true };
@@ -95,7 +95,7 @@
     GrRenderTargetProxy(LazyInstantiateCallback&&, LazyInstantiationType lazyType,
                         const GrBackendFormat&, const GrSurfaceDesc&, GrSurfaceOrigin,
                         const GrSwizzle& textureSwizzle, const GrSwizzle& outputSwizzle,
-                        SkBackingFit, SkBudgeted, GrInternalSurfaceFlags,
+                        SkBackingFit, SkBudgeted, GrProtected, GrInternalSurfaceFlags,
                         WrapsVkSecondaryCB wrapsVkSecondaryCB);
 
     // Wrapped version
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index d49721c..ed3565b 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -78,6 +78,7 @@
 
 sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
                                                    GrRenderable renderable, SkBudgeted budgeted,
+                                                   GrProtected isProtected,
                                                    const GrMipLevel texels[], int mipLevelCount) {
     ASSERT_SINGLE_OWNER
 
@@ -110,13 +111,14 @@
             h = std::max(h / 2, 1);
         }
     }
-    return fGpu->createTexture(desc, renderable, budgeted, tmpTexels.get(), mipLevelCount);
+    return fGpu->createTexture(desc, renderable, budgeted, isProtected, tmpTexels.get(),
+                               mipLevelCount);
 }
 
 sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
                                                      GrRenderable renderable, SkBudgeted budgeted,
-                                                     Flags flags) {
-    sk_sp<GrTexture> tex(this->refScratchTexture(desc, renderable, flags));
+                                                     GrProtected isProtected, Flags flags) {
+    sk_sp<GrTexture> tex(this->refScratchTexture(desc, renderable, isProtected, flags));
     if (tex && SkBudgeted::kNo == budgeted) {
         tex->resourcePriv().makeUnbudgeted();
     }
@@ -128,6 +130,7 @@
                                                    GrRenderable renderable,
                                                    SkBudgeted budgeted,
                                                    SkBackingFit fit,
+                                                   GrProtected isProtected,
                                                    const GrMipLevel& mipLevel,
                                                    Flags flags) {
     ASSERT_SINGLE_OWNER
@@ -159,9 +162,10 @@
     }
 
     GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
-    sk_sp<GrTexture> tex = (SkBackingFit::kApprox == fit)
-                                   ? this->createApproxTexture(desc, renderable, flags)
-                                   : this->createTexture(desc, renderable, budgeted, flags);
+    sk_sp<GrTexture> tex =
+            (SkBackingFit::kApprox == fit)
+                    ? this->createApproxTexture(desc, renderable, isProtected, flags)
+                    : this->createTexture(desc, renderable, budgeted, isProtected, flags);
     if (!tex) {
         return nullptr;
     }
@@ -197,7 +201,7 @@
 
 sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
                                                    GrRenderable renderable, SkBudgeted budgeted,
-                                                   Flags flags) {
+                                                   GrProtected isProtected, Flags flags) {
     ASSERT_SINGLE_OWNER
     if (this->isAbandoned()) {
         return nullptr;
@@ -209,7 +213,8 @@
 
     // Compressed textures are read-only so they don't support re-use for scratch.
     if (!GrPixelConfigIsCompressed(desc.fConfig)) {
-        sk_sp<GrTexture> tex = this->getExactScratch(desc, renderable, budgeted, flags);
+        sk_sp<GrTexture> tex =
+                this->getExactScratch(desc, renderable, budgeted, isProtected, flags);
         if (tex) {
             return tex;
         }
@@ -222,10 +227,10 @@
         GrMipLevel level;
         level.fRowBytes = rowBytes;
         level.fPixels = zeros.get();
-        return fGpu->createTexture(desc, renderable, budgeted, &level, 1);
+        return fGpu->createTexture(desc, renderable, budgeted, isProtected, &level, 1);
     }
 
-    return fGpu->createTexture(desc, renderable, budgeted);
+    return fGpu->createTexture(desc, renderable, budgeted, isProtected);
 }
 
 // Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
@@ -255,7 +260,8 @@
 }
 
 sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
-                                                         GrRenderable renderable, Flags flags) {
+                                                         GrRenderable renderable,
+                                                         GrProtected isProtected, Flags flags) {
     ASSERT_SINGLE_OWNER
     SkASSERT(Flags::kNone == flags || Flags::kNoPendingIO == flags);
 
@@ -272,7 +278,7 @@
         return nullptr;
     }
 
-    if (auto tex = this->refScratchTexture(desc, renderable, flags)) {
+    if (auto tex = this->refScratchTexture(desc, renderable, isProtected, flags)) {
         return tex;
     }
 
@@ -285,7 +291,7 @@
         wdesc->fHeight = MakeApprox(wdesc->fHeight);
     }
 
-    if (auto tex = this->refScratchTexture(*copyDesc, renderable, flags)) {
+    if (auto tex = this->refScratchTexture(*copyDesc, renderable, isProtected, flags)) {
         return tex;
     }
 
@@ -296,13 +302,14 @@
         GrMipLevel level;
         level.fRowBytes = rowBytes;
         level.fPixels = zeros.get();
-        return fGpu->createTexture(*copyDesc, renderable, SkBudgeted::kYes, &level, 1);
+        return fGpu->createTexture(*copyDesc, renderable, SkBudgeted::kYes, isProtected, &level, 1);
     }
-    return fGpu->createTexture(*copyDesc, renderable, SkBudgeted::kYes);
+    return fGpu->createTexture(*copyDesc, renderable, SkBudgeted::kYes, isProtected);
 }
 
 sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
-                                                       GrRenderable renderable, Flags flags) {
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected, Flags flags) {
     ASSERT_SINGLE_OWNER
     SkASSERT(!this->isAbandoned());
     SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 3447fd4..74c4c6d 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -75,18 +75,18 @@
      * GrRenderTarget. The texture's format and sample count will always match the request.
      * The contents of the texture are undefined.
      */
-    sk_sp<GrTexture> createApproxTexture(const GrSurfaceDesc&, GrRenderable, Flags);
+    sk_sp<GrTexture> createApproxTexture(const GrSurfaceDesc&, GrRenderable, GrProtected, Flags);
 
     /** Create an exact fit texture with no initial data to upload. */
-    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted,
+    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
                                    Flags = Flags::kNone);
 
-    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted,
+    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
                                    const GrMipLevel texels[], int mipLevelCount);
 
     /** Create a potentially loose fit texture with the provided data */
-    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable renderable, SkBudgeted,
-                                   SkBackingFit, const GrMipLevel&, Flags);
+    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, SkBackingFit,
+                                   GrProtected, const GrMipLevel&, Flags);
 
     /**
      * Creates a compressed texture. The GrGpu must support the SkImageImage::Compression type.
@@ -266,13 +266,14 @@
 
     // Attempts to find a resource in the cache that exactly matches the GrSurfaceDesc. Failing that
     // it returns null. If non-null, the resulting texture is always budgeted.
-    sk_sp<GrTexture> refScratchTexture(const GrSurfaceDesc&, GrRenderable, Flags);
+    sk_sp<GrTexture> refScratchTexture(const GrSurfaceDesc&, GrRenderable, GrProtected, Flags);
 
     /*
      * Try to find an existing scratch texture that exactly matches 'desc'. If successful
      * update the budgeting accordingly.
      */
-    sk_sp<GrTexture> getExactScratch(const GrSurfaceDesc&, GrRenderable, SkBudgeted, Flags);
+    sk_sp<GrTexture> getExactScratch(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
+                                     Flags);
 
     GrResourceCache* cache() { return fCache; }
     const GrResourceCache* cache() const { return fCache; }
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 425b91b..99f7699 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -185,7 +185,7 @@
             context->priv().caps()->getBackendFormatFromColorType(GrColorType::kAlpha_8);
 
     return proxyProvider->createProxy(format, desc, GrRenderable::kNo, kTopLeft_GrSurfaceOrigin,
-                                      fit, SkBudgeted::kYes);
+                                      fit, SkBudgeted::kYes, GrProtected::kNo);
 }
 
 namespace {
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 1882e3c..6ec45d8 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -309,7 +309,7 @@
                 this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin : dstProxy->origin();
         auto tempProxy = direct->priv().proxyProvider()->createProxy(
                 format, desc, GrRenderable::kNo, tempOrigin, SkBackingFit::kApprox,
-                SkBudgeted::kYes);
+                SkBudgeted::kYes, GrProtected::kNo);
 
         if (!tempProxy) {
             return false;
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index c0b2baa..a82559c 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -55,7 +55,8 @@
                                const GrBackendFormat& format, const GrSurfaceDesc& desc,
                                GrRenderable renderable, GrSurfaceOrigin origin,
                                const GrSwizzle& textureSwizzle, SkBackingFit fit,
-                               SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
+                               SkBudgeted budgeted, GrProtected isProtected,
+                               GrInternalSurfaceFlags surfaceFlags)
         : fSurfaceFlags(surfaceFlags)
         , fFormat(format)
         , fConfig(desc.fConfig)
@@ -67,7 +68,7 @@
         , fBudgeted(budgeted)
         , fLazyInstantiateCallback(std::move(callback))
         , fLazyInstantiationType(lazyType)
-        , fIsProtected(desc.fIsProtected)
+        , fIsProtected(isProtected)
         , fGpuMemorySize(kInvalidGpuMemorySize)
         , fLastOpList(nullptr) {
     SkASSERT(fFormat.isValid());
@@ -138,7 +139,6 @@
     GrSurfaceDesc desc;
     desc.fWidth = fWidth;
     desc.fHeight = fHeight;
-    desc.fIsProtected = fIsProtected;
     desc.fConfig = fConfig;
     desc.fSampleCnt = sampleCnt;
 
@@ -163,18 +163,18 @@
             texels[i].fRowBytes = 0;
         }
 
-        surface = resourceProvider->createTexture(desc, renderable, fBudgeted, texels.get(),
-                                                  mipCount);
+        surface = resourceProvider->createTexture(desc, renderable, fBudgeted, fIsProtected,
+                                                  texels.get(), mipCount);
         if (surface) {
             SkASSERT(surface->asTexture());
             SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
         }
     } else {
         if (SkBackingFit::kApprox == fFit) {
-            surface =
-                    resourceProvider->createApproxTexture(desc, renderable, resourceProviderFlags);
+            surface = resourceProvider->createApproxTexture(desc, renderable, fIsProtected,
+                                                            resourceProviderFlags);
         } else {
-            surface = resourceProvider->createTexture(desc, renderable, fBudgeted,
+            surface = resourceProvider->createTexture(desc, renderable, fBudgeted, fIsProtected,
                                                       resourceProviderFlags);
         }
     }
diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h
index 33c3688..0d241c7 100644
--- a/src/gpu/GrSurfaceProxy.h
+++ b/src/gpu/GrSurfaceProxy.h
@@ -327,16 +327,17 @@
     // Deferred version
     GrSurfaceProxy(const GrBackendFormat& format, const GrSurfaceDesc& desc,
                    GrRenderable renderable, GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
-                   SkBackingFit fit, SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
+                   SkBackingFit fit, SkBudgeted budgeted, GrProtected isProtected,
+                   GrInternalSurfaceFlags surfaceFlags)
             : GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse, format, desc, renderable,
-                             origin, textureSwizzle, fit, budgeted, surfaceFlags) {
+                             origin, textureSwizzle, fit, budgeted, isProtected, surfaceFlags) {
         // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
     }
 
     // Lazy-callback version
     GrSurfaceProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrBackendFormat& format,
                    const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
-                   const GrSwizzle& textureSwizzle, SkBackingFit, SkBudgeted,
+                   const GrSwizzle& textureSwizzle, SkBackingFit, SkBudgeted, GrProtected,
                    GrInternalSurfaceFlags);
 
     // Wrapped version.
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 76e841a..1877e53 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -36,9 +36,11 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-GrTexture::GrTexture(GrGpu* gpu, const GrSurfaceDesc& desc, GrTextureType textureType,
-                     GrMipMapsStatus mipMapsStatus)
-        : INHERITED(gpu, desc), fTextureType(textureType), fMipMapsStatus(mipMapsStatus) {
+GrTexture::GrTexture(GrGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
+                     GrTextureType textureType, GrMipMapsStatus mipMapsStatus)
+        : INHERITED(gpu, desc, isProtected)
+        , fTextureType(textureType)
+        , fMipMapsStatus(mipMapsStatus) {
     if (GrMipMapsStatus::kNotAllocated == fMipMapsStatus) {
         fMaxMipMapLevel = 0;
     } else {
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index ce3111e..a71b9f3 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -19,9 +19,10 @@
 GrTextureProxy::GrTextureProxy(const GrBackendFormat& format, const GrSurfaceDesc& srcDesc,
                                GrSurfaceOrigin origin, GrMipMapped mipMapped,
                                const GrSwizzle& textureSwizzle, SkBackingFit fit,
-                               SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
+                               SkBudgeted budgeted, GrProtected isProtected,
+                               GrInternalSurfaceFlags surfaceFlags)
         : INHERITED(format, srcDesc, GrRenderable::kNo, origin, textureSwizzle, fit, budgeted,
-                    surfaceFlags)
+                    isProtected, surfaceFlags)
         , fMipMapped(mipMapped)
         , fProxyProvider(nullptr)
         , fDeferredUploader(nullptr) {}
@@ -31,9 +32,9 @@
                                const GrBackendFormat& format, const GrSurfaceDesc& desc,
                                GrSurfaceOrigin origin, GrMipMapped mipMapped,
                                const GrSwizzle& texSwizzle, SkBackingFit fit, SkBudgeted budgeted,
-                               GrInternalSurfaceFlags surfaceFlags)
+                               GrProtected isProtected, GrInternalSurfaceFlags surfaceFlags)
         : INHERITED(std::move(callback), lazyType, format, desc, GrRenderable::kNo, origin,
-                    texSwizzle, fit, budgeted, surfaceFlags)
+                    texSwizzle, fit, budgeted, isProtected, surfaceFlags)
         , fMipMapped(mipMapped)
         , fProxyProvider(nullptr)
         , fDeferredUploader(nullptr) {}
diff --git a/src/gpu/GrTextureProxy.h b/src/gpu/GrTextureProxy.h
index 251f6ad..c0f24dc 100644
--- a/src/gpu/GrTextureProxy.h
+++ b/src/gpu/GrTextureProxy.h
@@ -94,7 +94,7 @@
     // Deferred version - no data.
     GrTextureProxy(const GrBackendFormat&, const GrSurfaceDesc& srcDesc, GrSurfaceOrigin,
                    GrMipMapped, const GrSwizzle& textureSwizzle, SkBackingFit, SkBudgeted,
-                   GrInternalSurfaceFlags);
+                   GrProtected, GrInternalSurfaceFlags);
 
     // Lazy-callback version
     // There are two main use cases for lazily-instantiated proxies:
@@ -108,7 +108,7 @@
     // know the final size until flush time.
     GrTextureProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrBackendFormat&,
                    const GrSurfaceDesc& desc, GrSurfaceOrigin, GrMipMapped, const GrSwizzle&,
-                   SkBackingFit, SkBudgeted, GrInternalSurfaceFlags);
+                   SkBackingFit, SkBudgeted, GrProtected, GrInternalSurfaceFlags);
 
     // Wrapped version
     GrTextureProxy(sk_sp<GrSurface>, GrSurfaceOrigin, const GrSwizzle&);
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index 2d010de..22a02f9 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -27,14 +27,15 @@
                                                        const GrSwizzle& outSwizzle,
                                                        SkBackingFit fit,
                                                        SkBudgeted budgeted,
+                                                       GrProtected isProtected,
                                                        GrInternalSurfaceFlags surfaceFlags)
         : GrSurfaceProxy(format, desc, GrRenderable::kYes, origin, texSwizzle, fit, budgeted,
-                         surfaceFlags)
+                         isProtected, surfaceFlags)
         // for now textures w/ data are always wrapped
         , GrRenderTargetProxy(caps, format, desc, origin, texSwizzle, outSwizzle, fit, budgeted,
-                              surfaceFlags)
-        , GrTextureProxy(format, desc, origin, mipMapped, texSwizzle, fit, budgeted, surfaceFlags) {
-}
+                              isProtected, surfaceFlags)
+        , GrTextureProxy(format, desc, origin, mipMapped, texSwizzle, fit, budgeted, isProtected,
+                         surfaceFlags) {}
 
 // Lazy-callback version
 GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(LazyInstantiateCallback&& callback,
@@ -47,15 +48,17 @@
                                                        const GrSwizzle& outSwizzle,
                                                        SkBackingFit fit,
                                                        SkBudgeted budgeted,
+                                                       GrProtected isProtected,
                                                        GrInternalSurfaceFlags surfaceFlags)
         : GrSurfaceProxy(std::move(callback), lazyType, format, desc, GrRenderable::kYes, origin,
-                         texSwizzle, fit, budgeted, surfaceFlags)
+                         texSwizzle, fit, budgeted, isProtected, surfaceFlags)
         // Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
         // callbacks to the texture and RT proxies simply to route to the appropriate constructors.
         , GrRenderTargetProxy(LazyInstantiateCallback(), lazyType, format, desc, origin, texSwizzle,
-                              outSwizzle, fit, budgeted, surfaceFlags, WrapsVkSecondaryCB::kNo)
+                              outSwizzle, fit, budgeted, isProtected, surfaceFlags,
+                              WrapsVkSecondaryCB::kNo)
         , GrTextureProxy(LazyInstantiateCallback(), lazyType, format, desc, origin, mipMapped,
-                         texSwizzle, fit, budgeted, surfaceFlags) {}
+                         texSwizzle, fit, budgeted, isProtected, surfaceFlags) {}
 
 // Wrapped version
 // This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
diff --git a/src/gpu/GrTextureRenderTargetProxy.h b/src/gpu/GrTextureRenderTargetProxy.h
index 995a3e9..efd1432 100644
--- a/src/gpu/GrTextureRenderTargetProxy.h
+++ b/src/gpu/GrTextureRenderTargetProxy.h
@@ -31,14 +31,14 @@
     GrTextureRenderTargetProxy(const GrCaps&, const GrBackendFormat&, const GrSurfaceDesc&,
                                GrSurfaceOrigin, GrMipMapped, const GrSwizzle& textureSwizzle,
                                const GrSwizzle& outputSwizzle, SkBackingFit, SkBudgeted,
-                               GrInternalSurfaceFlags);
+                               GrProtected, GrInternalSurfaceFlags);
 
     // Lazy-callback version
     GrTextureRenderTargetProxy(LazyInstantiateCallback&&, LazyInstantiationType,
                                const GrBackendFormat&, const GrSurfaceDesc& desc, GrSurfaceOrigin,
                                GrMipMapped, const GrSwizzle& textureSwizzle,
                                const GrSwizzle& outputSwizzle, SkBackingFit, SkBudgeted,
-                               GrInternalSurfaceFlags);
+                               GrProtected, GrInternalSurfaceFlags);
 
     // Wrapped version
     GrTextureRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin, const GrSwizzle& textureSwizzle,
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index f14380f..3a5eca3 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -84,18 +84,19 @@
 
     fTextureProxy = GrProxyProvider::MakeFullyLazyProxy(
             [this, pixelConfig](GrResourceProvider* resourceProvider) {
-                    if (!fBackingTexture) {
-                        GrSurfaceDesc desc;
-                        desc.fWidth = fWidth;
-                        desc.fHeight = fHeight;
-                        desc.fConfig = pixelConfig;
-                        fBackingTexture = resourceProvider->createTexture(
-                                desc, GrRenderable::kYes, SkBudgeted::kYes,
-                                GrResourceProvider::Flags::kNoPendingIO);
-                    }
-                    return GrSurfaceProxy::LazyInstantiationResult(fBackingTexture);
+                if (!fBackingTexture) {
+                    GrSurfaceDesc desc;
+                    desc.fWidth = fWidth;
+                    desc.fHeight = fHeight;
+                    desc.fConfig = pixelConfig;
+                    fBackingTexture = resourceProvider->createTexture(
+                            desc, GrRenderable::kYes, SkBudgeted::kYes, GrProtected::kNo,
+                            GrResourceProvider::Flags::kNoPendingIO);
+                }
+                return GrSurfaceProxy::LazyInstantiationResult(fBackingTexture);
             },
-            format, GrProxyProvider::Renderable::kYes, kTextureOrigin, pixelConfig, caps);
+            format, GrProxyProvider::Renderable::kYes, GrProtected::kNo, kTextureOrigin,
+            pixelConfig, caps);
 
     fTextureProxy->priv().setIgnoredByResourceAllocator();
 }
diff --git a/src/gpu/ccpr/GrCCClipPath.cpp b/src/gpu/ccpr/GrCCClipPath.cpp
index 579489e..075e2b2 100644
--- a/src/gpu/ccpr/GrCCClipPath.cpp
+++ b/src/gpu/ccpr/GrCCClipPath.cpp
@@ -43,7 +43,7 @@
 
                 return std::move(texture);
             },
-            format, GrProxyProvider::Renderable::kYes, kTopLeft_GrSurfaceOrigin,
+            format, GrProxyProvider::Renderable::kYes, GrProtected::kNo, kTopLeft_GrSurfaceOrigin,
             kAlpha_half_GrPixelConfig, caps);
 
     fDeviceSpacePath = deviceSpacePath;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 4508af7..58bd698 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -676,6 +676,10 @@
     } else if (GR_GL_TEXTURE_2D != idDesc->fInfo.fTarget) {
         return false;
     }
+    if (backendTex.isProtected()) {
+        // Not supported in GL backend at this time.
+        return false;
+    }
     return true;
 }
 
@@ -770,6 +774,11 @@
         return nullptr;
     }
 
+    if (backendRT.isProtected()) {
+        // Not supported in GL at this time.
+        return nullptr;
+    }
+
     GrGLRenderTarget::IDDesc idDesc;
     idDesc.fRTFBOID = info.fFBOID;
     idDesc.fMSColorRenderbufferID = 0;
@@ -1463,8 +1472,13 @@
 sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
                                           GrRenderable renderable,
                                           SkBudgeted budgeted,
+                                          GrProtected isProtected,
                                           const GrMipLevel texels[],
                                           int mipLevelCount) {
+    // We don't support protected textures in GL.
+    if (isProtected == GrProtected::kYes) {
+        return nullptr;
+    }
     // We fail if the MSAA was requested and is not available.
     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt > 1) {
         return return_null_texture();
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index fb5c196..c6d65b3 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -191,7 +191,7 @@
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
 
-    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, GrRenderable, SkBudgeted,
+    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
                                      const GrMipLevel[], int mipLevelCount) override;
     sk_sp<GrTexture> onCreateCompressedTexture(int width, int height,
                                                SkImage::CompressionType compression, SkBudgeted,
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index 9c56b60..0b48f73 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -24,8 +24,8 @@
                                    GrGLenum format,
                                    const IDDesc& idDesc,
                                    GrGLStencilAttachment* stencil)
-    : GrSurface(gpu, desc)
-    , INHERITED(gpu, desc, stencil) {
+    : GrSurface(gpu, desc, GrProtected::kNo)
+    , INHERITED(gpu, desc, GrProtected::kNo, stencil) {
     this->setFlags(gpu->glCaps(), idDesc);
     this->init(desc, format, idDesc);
     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
@@ -33,8 +33,8 @@
 
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrGLenum format,
                                    const IDDesc& idDesc)
-    : GrSurface(gpu, desc)
-    , INHERITED(gpu, desc) {
+    : GrSurface(gpu, desc, GrProtected::kNo)
+    , INHERITED(gpu, desc, GrProtected::kNo) {
     this->setFlags(gpu->glCaps(), idDesc);
     this->init(desc, format, idDesc);
 }
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index 4ae31da..ff25b38 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -47,8 +47,9 @@
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
                          const IDDesc& idDesc, GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, TextureTypeFromTarget(idDesc.fInfo.fTarget),
+                    mipMapsStatus)
         , fParameters(sk_make_sp<GrGLTextureParameters>()) {
     this->init(desc, idDesc);
     this->registerWithCache(budgeted);
@@ -60,8 +61,9 @@
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
                          const IDDesc& idDesc, sk_sp<GrGLTextureParameters> parameters,
                          GrWrapCacheable cacheable, GrIOType ioType)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, TextureTypeFromTarget(idDesc.fInfo.fTarget),
+                    mipMapsStatus)
         , fParameters(std::move(parameters)) {
     SkASSERT(fParameters);
     this->init(desc, idDesc);
@@ -73,8 +75,9 @@
 
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
                          sk_sp<GrGLTextureParameters> parameters, GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus) {
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, TextureTypeFromTarget(idDesc.fInfo.fTarget),
+                    mipMapsStatus) {
     SkASSERT(parameters || idDesc.fOwnership == GrBackendObjectOwnership::kOwned);
     fParameters = parameters ? std::move(parameters) : sk_make_sp<GrGLTextureParameters>();
     this->init(desc, idDesc);
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index 6739b79..b46538a 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -18,7 +18,7 @@
                                                  const GrGLTexture::IDDesc& texIDDesc,
                                                  const GrGLRenderTarget::IDDesc& rtIDDesc,
                                                  GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrGLTexture(gpu, desc, texIDDesc, nullptr, mipMapsStatus)
         , GrGLRenderTarget(gpu, desc, texIDDesc.fInfo.fFormat, rtIDDesc) {
     this->registerWithCache(budgeted);
@@ -31,7 +31,7 @@
                                                  const GrGLRenderTarget::IDDesc& rtIDDesc,
                                                  GrWrapCacheable cacheable,
                                                  GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrGLTexture(gpu, desc, texIDDesc, std::move(parameters), mipMapsStatus)
         , GrGLRenderTarget(gpu, desc, texIDDesc.fInfo.fFormat, rtIDDesc) {
     this->registerWithCacheWrapped(cacheable);
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index e6f0a62..354b381 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -86,8 +86,8 @@
 }
 
 sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc, GrRenderable renderable,
-                                            SkBudgeted budgeted, const GrMipLevel texels[],
-                                            int mipLevelCount) {
+                                            SkBudgeted budgeted, GrProtected isProtected,
+                                            const GrMipLevel texels[], int mipLevelCount) {
     if (fMockOptions.fFailTextureAllocations) {
         return nullptr;
     }
@@ -102,10 +102,11 @@
     GrMockTextureInfo texInfo(ct, NextInternalTextureID());
     if (renderable == GrRenderable::kYes) {
         GrMockRenderTargetInfo rtInfo(ct, NextInternalRenderTargetID());
-        return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, budgeted, desc, mipMapsStatus,
-                                                              texInfo, rtInfo));
+        return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, budgeted, desc, isProtected,
+                                                              mipMapsStatus, texInfo, rtInfo));
     }
-    return sk_sp<GrTexture>(new GrMockTexture(this, budgeted, desc, mipMapsStatus, texInfo));
+    return sk_sp<GrTexture>(
+            new GrMockTexture(this, budgeted, desc, isProtected, mipMapsStatus, texInfo));
 }
 
 sk_sp<GrTexture> GrMockGpu::onCreateCompressedTexture(int width, int height,
@@ -127,8 +128,9 @@
 
     GrMipMapsStatus mipMapsStatus = tex.hasMipMaps() ? GrMipMapsStatus::kValid
                                                      : GrMipMapsStatus::kNotAllocated;
-
-    return sk_sp<GrTexture>(new GrMockTexture(this, desc, mipMapsStatus, info, wrapType, ioType));
+    auto isProtected = GrProtected(tex.isProtected());
+    return sk_sp<GrTexture>(
+            new GrMockTexture(this, desc, isProtected, mipMapsStatus, info, wrapType, ioType));
 }
 
 sk_sp<GrTexture> GrMockGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
@@ -151,8 +153,9 @@
     // The client gave us the texture ID but we supply the render target ID.
     GrMockRenderTargetInfo rtInfo(texInfo.fColorType, NextInternalRenderTargetID());
 
-    return sk_sp<GrTexture>(
-            new GrMockTextureRenderTarget(this, desc, mipMapsStatus, texInfo, rtInfo, cacheable));
+    auto isProtected = GrProtected(tex.isProtected());
+    return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, desc, isProtected, mipMapsStatus,
+                                                          texInfo, rtInfo, cacheable));
 }
 
 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
@@ -164,8 +167,9 @@
     desc.fHeight = rt.height();
     desc.fConfig = info.pixelConfig();
 
+    auto isProtected = GrProtected(rt.isProtected());
     return sk_sp<GrRenderTarget>(
-            new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, info));
+            new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, isProtected, info));
 }
 
 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
@@ -182,8 +186,9 @@
     // The client gave us the texture ID but we supply the render target ID.
     GrMockRenderTargetInfo rtInfo(texInfo.fColorType, NextInternalRenderTargetID());
 
+    auto isProtected = GrProtected(tex.isProtected());
     return sk_sp<GrRenderTarget>(
-            new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, rtInfo));
+            new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, isProtected, rtInfo));
 }
 
 sk_sp<GrGpuBuffer> GrMockGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 1459637..da03b6a 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -63,7 +63,7 @@
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
 
-    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted,
+    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
                                      const GrMipLevel[], int mipLevelCount) override;
 
     sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h
index 44da34d..6a60141 100644
--- a/src/gpu/mock/GrMockTexture.h
+++ b/src/gpu/mock/GrMockTexture.h
@@ -18,14 +18,16 @@
 class GrMockTexture : public GrTexture {
 public:
     GrMockTexture(GrMockGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
-                  GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& info)
-            : GrMockTexture(gpu, desc, mipMapsStatus, info) {
+                  GrProtected isProtected, GrMipMapsStatus mipMapsStatus,
+                  const GrMockTextureInfo& info)
+            : GrMockTexture(gpu, desc, isProtected, mipMapsStatus, info) {
         this->registerWithCache(budgeted);
     }
 
-    GrMockTexture(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
-                  const GrMockTextureInfo& info, GrWrapCacheable cacheable, GrIOType ioType)
-            : GrMockTexture(gpu, desc, mipMapsStatus, info) {
+    GrMockTexture(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
+                  GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& info,
+                  GrWrapCacheable cacheable, GrIOType ioType)
+            : GrMockTexture(gpu, desc, isProtected, mipMapsStatus, info) {
         if (ioType == kRead_GrIOType) {
             this->setReadOnly();
         }
@@ -47,10 +49,10 @@
 
 protected:
     // constructor for subclasses
-    GrMockTexture(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
-                  const GrMockTextureInfo& info)
-            : GrSurface(gpu, desc)
-            , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+    GrMockTexture(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
+                  GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& info)
+            : GrSurface(gpu, desc, isProtected)
+            , INHERITED(gpu, desc, isProtected, GrTextureType::k2D, mipMapsStatus)
             , fInfo(info) {}
 
     void onRelease() override {
@@ -74,15 +76,15 @@
 class GrMockRenderTarget : public GrRenderTarget {
 public:
     GrMockRenderTarget(GrMockGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
-                       const GrMockRenderTargetInfo& info)
-            : GrSurface(gpu, desc), INHERITED(gpu, desc), fInfo(info) {
+                       GrProtected isProtected, const GrMockRenderTargetInfo& info)
+            : GrSurface(gpu, desc, isProtected), INHERITED(gpu, desc, isProtected), fInfo(info) {
         this->registerWithCache(budgeted);
     }
 
     enum Wrapped { kWrapped };
-    GrMockRenderTarget(GrMockGpu* gpu, Wrapped, const GrSurfaceDesc& desc,
+    GrMockRenderTarget(GrMockGpu* gpu, Wrapped, const GrSurfaceDesc& desc, GrProtected isProtected,
                        const GrMockRenderTargetInfo& info)
-            : GrSurface(gpu, desc), INHERITED(gpu, desc), fInfo(info) {
+            : GrSurface(gpu, desc, isProtected), INHERITED(gpu, desc, isProtected), fInfo(info) {
         this->registerWithCacheWrapped(GrWrapCacheable::kNo);
     }
 
@@ -114,9 +116,9 @@
 
 protected:
     // constructor for subclasses
-    GrMockRenderTarget(GrMockGpu* gpu, const GrSurfaceDesc& desc,
+    GrMockRenderTarget(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
                        const GrMockRenderTargetInfo& info)
-            : GrSurface(gpu, desc), INHERITED(gpu, desc), fInfo(info) {}
+            : GrSurface(gpu, desc, isProtected), INHERITED(gpu, desc, isProtected), fInfo(info) {}
 
 private:
     GrMockRenderTargetInfo fInfo;
@@ -128,21 +130,22 @@
 public:
     // Internally created.
     GrMockTextureRenderTarget(GrMockGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
-                              GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& texInfo,
+                              GrProtected isProtected, GrMipMapsStatus mipMapsStatus,
+                              const GrMockTextureInfo& texInfo,
                               const GrMockRenderTargetInfo& rtInfo)
-            : GrSurface(gpu, desc)
-            , GrMockTexture(gpu, desc, mipMapsStatus, texInfo)
-            , GrMockRenderTarget(gpu, desc, rtInfo) {
+            : GrSurface(gpu, desc, isProtected)
+            , GrMockTexture(gpu, desc, isProtected, mipMapsStatus, texInfo)
+            , GrMockRenderTarget(gpu, desc, isProtected, rtInfo) {
         this->registerWithCache(budgeted);
     }
 
     // Renderable wrapped backend texture.
-    GrMockTextureRenderTarget(GrMockGpu* gpu, const GrSurfaceDesc& desc,
+    GrMockTextureRenderTarget(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrProtected isProtected,
                               GrMipMapsStatus mipMapsStatus, const GrMockTextureInfo& texInfo,
                               const GrMockRenderTargetInfo& rtInfo, GrWrapCacheable cacheble)
-            : GrSurface(gpu, desc)
-            , GrMockTexture(gpu, desc, mipMapsStatus, texInfo)
-            , GrMockRenderTarget(gpu, desc, rtInfo) {
+            : GrSurface(gpu, desc, isProtected)
+            , GrMockTexture(gpu, desc, isProtected, mipMapsStatus, texInfo)
+            , GrMockRenderTarget(gpu, desc, isProtected, rtInfo) {
         this->registerWithCacheWrapped(cacheble);
     }
 
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 16f35fc..7024f93 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -136,7 +136,8 @@
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
 
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, GrRenderable, SkBudgeted budgeted,
-                                     const GrMipLevel texels[], int mipLevelCount) override;
+                                     GrProtected, const GrMipLevel texels[],
+                                     int mipLevelCount) override;
     sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
                                                SkBudgeted, const void* data) override {
         return nullptr;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index ab7ea8a..d2e12f1 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -408,8 +408,12 @@
 }
 
 sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc, GrRenderable renderable,
-                                           SkBudgeted budgeted, const GrMipLevel texels[],
-                                           int mipLevelCount) {
+                                           SkBudgeted budgeted, GrProtected isProtected,
+                                           const GrMipLevel texels[], int mipLevelCount) {
+    // We don't support protected textures in Metal.
+    if (isProtected == GrProtected::kYes) {
+        return nullptr;
+    }
     int mipLevels = !mipLevelCount ? 1 : mipLevelCount;
 
     if (!fMtlCaps->isConfigTexturable(desc.fConfig)) {
diff --git a/src/gpu/mtl/GrMtlRenderTarget.mm b/src/gpu/mtl/GrMtlRenderTarget.mm
index 7d4d989..8e239e3 100644
--- a/src/gpu/mtl/GrMtlRenderTarget.mm
+++ b/src/gpu/mtl/GrMtlRenderTarget.mm
@@ -20,8 +20,8 @@
                                      id<MTLTexture> colorTexture,
                                      id<MTLTexture> resolveTexture,
                                      Wrapped)
-        : GrSurface(gpu, desc)
-        , GrRenderTarget(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , GrRenderTarget(gpu, desc, GrProtected::kNo)
         , fColorTexture(colorTexture)
         , fResolveTexture(resolveTexture) {
     SkASSERT(desc.fSampleCnt > 1);
@@ -32,8 +32,8 @@
                                      const GrSurfaceDesc& desc,
                                      id<MTLTexture> colorTexture,
                                      Wrapped)
-        : GrSurface(gpu, desc)
-        , GrRenderTarget(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , GrRenderTarget(gpu, desc, GrProtected::kNo)
         , fColorTexture(colorTexture)
         , fResolveTexture(nil) {
     SkASSERT(1 == desc.fSampleCnt);
@@ -45,8 +45,8 @@
                                      const GrSurfaceDesc& desc,
                                      id<MTLTexture> colorTexture,
                                      id<MTLTexture> resolveTexture)
-        : GrSurface(gpu, desc)
-        , GrRenderTarget(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , GrRenderTarget(gpu, desc, GrProtected::kNo)
         , fColorTexture(colorTexture)
         , fResolveTexture(resolveTexture) {
     SkASSERT(desc.fSampleCnt > 1);
@@ -55,8 +55,8 @@
 GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
                                      const GrSurfaceDesc& desc,
                                      id<MTLTexture> colorTexture)
-        : GrSurface(gpu, desc)
-        , GrRenderTarget(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , GrRenderTarget(gpu, desc, GrProtected::kNo)
         , fColorTexture(colorTexture)
         , fResolveTexture(nil) {
     SkASSERT(1 == desc.fSampleCnt);
diff --git a/src/gpu/mtl/GrMtlTexture.mm b/src/gpu/mtl/GrMtlTexture.mm
index 36cc835..6b27862 100644
--- a/src/gpu/mtl/GrMtlTexture.mm
+++ b/src/gpu/mtl/GrMtlTexture.mm
@@ -20,8 +20,8 @@
                            const GrSurfaceDesc& desc,
                            id<MTLTexture> texture,
                            GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, GrTextureType::k2D, mipMapsStatus)
         , fTexture(texture) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == texture.mipmapLevelCount));
     this->registerWithCache(budgeted);
@@ -34,8 +34,8 @@
                            GrMipMapsStatus mipMapsStatus,
                            GrWrapCacheable cacheable,
                            GrIOType ioType)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, GrTextureType::k2D, mipMapsStatus)
         , fTexture(texture) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == texture.mipmapLevelCount));
     if (ioType == kRead_GrIOType) {
@@ -48,8 +48,8 @@
                            const GrSurfaceDesc& desc,
                            id<MTLTexture> texture,
                            GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        : GrSurface(gpu, desc, GrProtected::kNo)
+        , INHERITED(gpu, desc, GrProtected::kNo, GrTextureType::k2D, mipMapsStatus)
         , fTexture(texture) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == texture.mipmapLevelCount));
 }
diff --git a/src/gpu/mtl/GrMtlTextureRenderTarget.mm b/src/gpu/mtl/GrMtlTextureRenderTarget.mm
index 828b04a..7c86b61 100644
--- a/src/gpu/mtl/GrMtlTextureRenderTarget.mm
+++ b/src/gpu/mtl/GrMtlTextureRenderTarget.mm
@@ -19,7 +19,7 @@
                                                    id<MTLTexture> colorTexture,
                                                    id<MTLTexture> resolveTexture,
                                                    GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus)
         , GrMtlRenderTarget(gpu, desc, colorTexture, resolveTexture) {
     this->registerWithCache(budgeted);
@@ -30,7 +30,7 @@
                                                    const GrSurfaceDesc& desc,
                                                    id<MTLTexture> colorTexture,
                                                    GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus)
         , GrMtlRenderTarget(gpu, desc, colorTexture) {
     this->registerWithCache(budgeted);
@@ -42,7 +42,7 @@
                                                    id<MTLTexture> resolveTexture,
                                                    GrMipMapsStatus mipMapsStatus,
                                                    GrWrapCacheable cacheable)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus)
         , GrMtlRenderTarget(gpu, desc, colorTexture, resolveTexture) {
     this->registerWithCacheWrapped(cacheable);
@@ -53,7 +53,7 @@
                                                    id<MTLTexture> colorTexture,
                                                    GrMipMapsStatus mipMapsStatus,
                                                    GrWrapCacheable cacheable)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, GrProtected::kNo)
         , GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus)
         , GrMtlRenderTarget(gpu, desc, colorTexture) {
     this->registerWithCacheWrapped(cacheable);
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index b040b81..e4625d1 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -408,8 +408,9 @@
             random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
     const GrBackendFormat format =
             context->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
-    auto proxy = context->priv().proxyProvider()->createProxy(
-            format, desc, GrRenderable::kNo, origin, SkBackingFit::kExact, SkBudgeted::kYes);
+    auto proxy = context->priv().proxyProvider()->createProxy(format, desc, GrRenderable::kNo,
+                                                              origin, SkBackingFit::kExact,
+                                                              SkBudgeted::kYes, GrProtected::kNo);
 
     do {
         if (random->nextBool()) {
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index d3bf54e..a1921fb 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -693,9 +693,9 @@
             context->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
 
     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
-    sk_sp<GrTextureProxy> proxy =
-            proxyProvider->createProxy(format, desc, GrRenderable::kNo, origin, mipMapped, fit,
-                                       SkBudgeted::kNo, GrInternalSurfaceFlags::kNone);
+    sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
+            format, desc, GrRenderable::kNo, origin, mipMapped, fit, SkBudgeted::kNo,
+            GrProtected::kNo, GrInternalSurfaceFlags::kNone);
 
     SkRect rect = GrTest::TestRect(random);
     SkRect srcRect;
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index b21fc2c..a394fc7 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -950,8 +950,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrRenderable renderable,
-                                          SkBudgeted budgeted, const GrMipLevel texels[],
-                                          int mipLevelCount) {
+                                          SkBudgeted budgeted, GrProtected isProtected,
+                                          const GrMipLevel texels[], int mipLevelCount) {
     VkFormat pixelFormat;
     SkAssertResult(GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat));
 
@@ -981,7 +981,7 @@
     imageDesc.fSamples = 1;
     imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
     imageDesc.fUsageFlags = usageFlags;
-    imageDesc.fIsProtected = desc.fIsProtected;
+    imageDesc.fIsProtected = isProtected;
 
     GrMipMapsStatus mipMapsStatus = GrMipMapsStatus::kNotAllocated;
     if (mipLevels > 1) {
@@ -1190,7 +1190,6 @@
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = 1;
-    surfDesc.fIsProtected = backendTex.isProtected() ? GrProtected::kYes : GrProtected::kNo;
 
     sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout();
     SkASSERT(layout);
@@ -1231,7 +1230,6 @@
     GrSurfaceDesc surfDesc;
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
-    surfDesc.fIsProtected = backendTex.isProtected() ? GrProtected::kYes : GrProtected::kNo;
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, colorType,
                                                                    backendTex.getBackendFormat());
@@ -1271,7 +1269,6 @@
     GrSurfaceDesc desc;
     desc.fWidth = backendRT.width();
     desc.fHeight = backendRT.height();
-    desc.fIsProtected = backendRT.isProtected() ? GrProtected::kYes : GrProtected::kNo;
     desc.fConfig = backendRT.config();
     desc.fSampleCnt = 1;
 
@@ -1310,7 +1307,6 @@
     GrSurfaceDesc desc;
     desc.fWidth = tex.width();
     desc.fHeight = tex.height();
-    desc.fIsProtected = tex.isProtected() ? GrProtected::kYes : GrProtected::kNo;
     desc.fConfig = tex.config();
     desc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config());
     if (!desc.fSampleCnt) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 45b0090..9d782f9 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -191,7 +191,7 @@
 
     void destroyResources();
 
-    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted,
+    sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, GrRenderable, SkBudgeted, GrProtected,
                                      const GrMipLevel[], int mipLevelCount) override;
     sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
                                                SkBudgeted, const void* data) override;
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 79e827f..28282dd 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -30,16 +30,17 @@
                                    sk_sp<GrVkImageLayout> msaaLayout,
                                    const GrVkImageView* colorAttachmentView,
                                    const GrVkImageView* resolveAttachmentView)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
         // for the moment we only support 1:1 color to stencil
-        , GrRenderTarget(gpu, desc)
+        , GrRenderTarget(gpu, desc, info.fProtected)
         , fColorAttachmentView(colorAttachmentView)
         , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
                                    GrBackendObjectOwnership::kOwned))
         , fResolveAttachmentView(resolveAttachmentView)
         , fFramebuffer(nullptr)
         , fCachedSimpleRenderPass(nullptr) {
+    SkASSERT(info.fProtected == msaaInfo.fProtected);
     SkASSERT(desc.fSampleCnt > 1);
     this->createFramebuffer(gpu);
     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
@@ -56,16 +57,17 @@
                                    const GrVkImageView* colorAttachmentView,
                                    const GrVkImageView* resolveAttachmentView,
                                    GrBackendObjectOwnership ownership)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), ownership)
         // for the moment we only support 1:1 color to stencil
-        , GrRenderTarget(gpu, desc)
+        , GrRenderTarget(gpu, desc, info.fProtected)
         , fColorAttachmentView(colorAttachmentView)
         , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
                                    GrBackendObjectOwnership::kOwned))
         , fResolveAttachmentView(resolveAttachmentView)
         , fFramebuffer(nullptr)
         , fCachedSimpleRenderPass(nullptr) {
+    SkASSERT(info.fProtected == msaaInfo.fProtected);
     SkASSERT(desc.fSampleCnt > 1);
     this->createFramebuffer(gpu);
 }
@@ -77,9 +79,9 @@
                                    const GrVkImageInfo& info,
                                    sk_sp<GrVkImageLayout> layout,
                                    const GrVkImageView* colorAttachmentView)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
-        , GrRenderTarget(gpu, desc)
+        , GrRenderTarget(gpu, desc, info.fProtected)
         , fColorAttachmentView(colorAttachmentView)
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
@@ -98,9 +100,9 @@
                                    sk_sp<GrVkImageLayout> layout,
                                    const GrVkImageView* colorAttachmentView,
                                    GrBackendObjectOwnership ownership)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), ownership)
-        , GrRenderTarget(gpu, desc)
+        , GrRenderTarget(gpu, desc, info.fProtected)
         , fColorAttachmentView(colorAttachmentView)
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
@@ -116,9 +118,9 @@
                                    sk_sp<GrVkImageLayout> layout,
                                    const GrVkRenderPass* renderPass,
                                    GrVkSecondaryCommandBuffer* secondaryCommandBuffer)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
-        , GrRenderTarget(gpu, desc)
+        , GrRenderTarget(gpu, desc, info.fProtected)
         , fColorAttachmentView(nullptr)
         , fMSAAImage(nullptr)
         , fResolveAttachmentView(nullptr)
@@ -156,7 +158,7 @@
                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
         msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
-        msImageDesc.fIsProtected = desc.fIsProtected;
+        msImageDesc.fIsProtected = info.fProtected;
 
         if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
             return nullptr;
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 3aba5f1..d30a3bd 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -25,9 +25,9 @@
                          sk_sp<GrVkImageLayout> layout,
                          const GrVkImageView* view,
                          GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
         , fTextureView(view) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
     this->registerWithCache(budgeted);
@@ -40,9 +40,9 @@
                          sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
                          GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
                          GrWrapCacheable cacheable, GrIOType ioType)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, std::move(layout), ownership)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
         , fTextureView(view) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
     if (ioType == kRead_GrIOType) {
@@ -59,9 +59,9 @@
                          const GrVkImageView* view,
                          GrMipMapsStatus mipMapsStatus,
                          GrBackendObjectOwnership ownership)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, layout, ownership)
-        , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
+        , INHERITED(gpu, desc, info.fProtected, GrTextureType::k2D, mipMapsStatus)
         , fTextureView(view) {
     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
 }
@@ -90,9 +90,11 @@
                                               imageView, mipMapsStatus));
 }
 
-sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
+sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
+                                                   const GrSurfaceDesc& desc,
                                                    GrWrapOwnership wrapOwnership,
-                                                   GrWrapCacheable cacheable, GrIOType ioType,
+                                                   GrWrapCacheable cacheable,
+                                                   GrIOType ioType,
                                                    const GrVkImageInfo& info,
                                                    sk_sp<GrVkImageLayout> layout) {
     // Adopted textures require both image and allocation because we're responsible for freeing
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index bba4103..dff2301 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -29,13 +29,14 @@
                                                  const GrVkImageView* colorAttachmentView,
                                                  const GrVkImageView* resolveAttachmentView,
                                                  GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, layout, GrBackendObjectOwnership::kOwned)
         , GrVkTexture(gpu, desc, info, layout, texView, mipMapsStatus,
                       GrBackendObjectOwnership::kOwned)
         , GrVkRenderTarget(gpu, desc, info, layout, msaaInfo, std::move(msaaLayout),
                            colorAttachmentView, resolveAttachmentView,
                            GrBackendObjectOwnership::kOwned) {
+    SkASSERT(info.fProtected == msaaInfo.fProtected);
     this->registerWithCache(budgeted);
 }
 
@@ -47,7 +48,7 @@
                                                  const GrVkImageView* texView,
                                                  const GrVkImageView* colorAttachmentView,
                                                  GrMipMapsStatus mipMapsStatus)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, layout, GrBackendObjectOwnership::kOwned)
         , GrVkTexture(gpu, desc, info, layout, texView, mipMapsStatus,
                       GrBackendObjectOwnership::kOwned)
@@ -68,11 +69,12 @@
                                                  GrMipMapsStatus mipMapsStatus,
                                                  GrBackendObjectOwnership ownership,
                                                  GrWrapCacheable cacheable)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, layout, ownership)
         , GrVkTexture(gpu, desc, info, layout, texView, mipMapsStatus, ownership)
         , GrVkRenderTarget(gpu, desc, info, layout, msaaInfo, std::move(msaaLayout),
                            colorAttachmentView, resolveAttachmentView, ownership) {
+    SkASSERT(info.fProtected == msaaInfo.fProtected);
     this->registerWithCacheWrapped(cacheable);
 }
 
@@ -85,7 +87,7 @@
                                                  GrMipMapsStatus mipMapsStatus,
                                                  GrBackendObjectOwnership ownership,
                                                  GrWrapCacheable cacheable)
-        : GrSurface(gpu, desc)
+        : GrSurface(gpu, desc, info.fProtected)
         , GrVkImage(info, layout, ownership)
         , GrVkTexture(gpu, desc, info, layout, texView, mipMapsStatus, ownership)
         , GrVkRenderTarget(gpu, desc, info, layout, colorAttachmentView, ownership) {
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index efce01d..fd863ac 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -489,8 +489,9 @@
     desc.fConfig = config;
 
     // We pass kReadOnly here since we should treat content of the client's texture as immutable.
+    // The promise API provides no way for the client to indicated that the texture is protected.
     return proxyProvider->createLazyProxy(
             std::move(callback), backendFormat, desc, GrRenderable::kNo, origin, mipMapped,
             GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo,
-            GrSurfaceProxy::LazyInstantiationType::kDeinstantiate);
+            GrProtected::kNo, GrSurfaceProxy::LazyInstantiationType::kDeinstantiate);
 }