Add hint to SkSurface::MakeRenderTarget that we will use mips

Additionally this changed triggered a cascade of plumbing GrMipMapped
down throughout Ganesh.

Bug: skia:
Change-Id: I4181f44d9046d66139bb491c7abf86703305aaeb
Reviewed-on: https://skia-review.googlesource.com/63000
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 890532f..dca38ce 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -116,11 +116,14 @@
 
     /**
      *  Return a new surface whose contents will be drawn to an offscreen
-     *  render target, allocated by the surface.
+     *  render target, allocated by the surface. The optional shouldCreateWithMips flag is a hint
+     *  that this surface may be snapped to an SkImage which will be used with mip maps so we should
+     *  create the backend gpu RenderTarget with mips to avoid a copy later on.
      */
     static sk_sp<SkSurface> MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
                                              int sampleCount, GrSurfaceOrigin,
-                                             const SkSurfaceProps*);
+                                             const SkSurfaceProps*,
+                                             bool shouldCreateWithMips = false);
 
     static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
                                              const SkImageInfo& info, int sampleCount,
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 65ac7ec..1056bdd 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -61,7 +61,7 @@
 
     static size_t WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2 = false);
     static size_t ComputeSize(GrPixelConfig config, int width, int height, int colorSamplesPerPixel,
-                              bool hasMIPMaps, bool useNextPow2 = false);
+                              GrMipMapped, bool useNextPow2 = false);
 
 protected:
     // Methods made available via GrSurfacePriv
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index fcccd36..2bbf02a 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -384,11 +384,11 @@
     void assign(sk_sp<GrSurface> surface);
 
     sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt, bool needsStencil,
-                                       GrSurfaceFlags flags, bool isMipMapped,
+                                       GrSurfaceFlags flags, GrMipMapped mipMapped,
                                        SkDestinationSurfaceColorMode mipColorMode) const;
 
     bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt, bool needsStencil,
-                         GrSurfaceFlags flags, bool isMipMapped,
+                         GrSurfaceFlags flags, GrMipMapped mipMapped,
                          SkDestinationSurfaceColorMode mipColorMode, const GrUniqueKey*);
 
     // For wrapped resources, 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always be filled in
diff --git a/include/private/GrTextureProxy.h b/include/private/GrTextureProxy.h
index e841bae..a761dca 100644
--- a/include/private/GrTextureProxy.h
+++ b/include/private/GrTextureProxy.h
@@ -37,7 +37,7 @@
         }
     }
 
-    bool isMipMapped() const { return fIsMipMapped; }
+    GrMipMapped mipMapped() const { return fMipMapped; }
 
     /**
      * Return the texture proxy's unique key. It will be invalid if the proxy doesn't have one.
@@ -85,7 +85,7 @@
     sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
 
 private:
-    bool fIsMipMapped;
+    GrMipMapped fMipMapped;
     SkDestinationSurfaceColorMode fMipColorMode;
 
     GrUniqueKey fUniqueKey;
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index 60cbf9c..7240c79 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -77,8 +77,7 @@
     context->getResourceCache()->insertCrossContextGpuResource(texture.get());
 
     GrBackend backend = context->contextPriv().getBackend();
-    GrMipMapped mipMapped = texture->texturePriv().hasMipMaps() ? GrMipMapped::kYes
-                                                                : GrMipMapped::kNo;
+    GrMipMapped mipMapped = texture->texturePriv().mipMapped();
     GrBackendTexture backendTexture = make_backend_texture_from_handle(backend,
                                                                        texture->width(),
                                                                        texture->height(),
@@ -177,7 +176,7 @@
 
     if (0 == origin.fX && 0 == origin.fY &&
         info.width() == fBackendTexture.width() && info.height() == fBackendTexture.height() &&
-        (!willNeedMipMaps || proxy->isMipMapped())) {
+        (!willNeedMipMaps || GrMipMapped::kYes == proxy->mipMapped())) {
         // If the caller wants the entire texture and we have the correct mip support, we're done
         return proxy;
     } else {
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index b92ffda..9b3ba36 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -42,7 +42,7 @@
     if (fOriginalKey.isValid()) {
         proxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
                                                             fOriginalKey, kTopLeft_GrSurfaceOrigin);
-        if (proxy && (!willBeMipped || proxy->isMipMapped())) {
+        if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             return proxy;
         }
     }
@@ -61,7 +61,7 @@
                 this->context()->resourceProvider()->assignUniqueKeyToProxy(fOriginalKey,
                                                                             proxy.get());
             }
-            if (!willBeMipped || proxy->isMipMapped()) {
+            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
                 if (fOriginalKey.isValid()) {
                     GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef());
@@ -73,7 +73,7 @@
 
     if (proxy) {
         SkASSERT(willBeMipped);
-        SkASSERT(!proxy->isMipMapped());
+        SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
         // We need a mipped proxy, but we either found a proxy earlier that wasn't mipped or
         // generated a non mipped proxy. Thus we generate a new mipped surface and copy the original
         // proxy into the base layer. We will then let the gpu generate the rest of the mips.
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 0c44ecf..1e13b8b 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -154,10 +154,21 @@
     return fRenderTargetProxy->asTextureProxy();
 }
 
+const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
+    return fRenderTargetProxy->asTextureProxy();
+}
+
 sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
     return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
 }
 
+GrMipMapped GrRenderTargetContext::mipMapped() const {
+    if (const GrTextureProxy* proxy = this->asTextureProxy()) {
+        return proxy->mipMapped();
+    }
+    return GrMipMapped::kNo;
+}
+
 GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
     ASSERT_SINGLE_OWNER
     SkDEBUGCODE(this->validate();)
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 50f402b..0ab1ee0 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -337,6 +337,7 @@
     const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
     GrColorSpaceXform* getColorXformFromSRGB() const { return fColorXformFromSRGB.get(); }
     GrSurfaceOrigin origin() const { return fRenderTargetProxy->origin(); }
+    GrMipMapped mipMapped() const;
 
     bool wasAbandoned() const;
 
@@ -356,6 +357,7 @@
     sk_sp<GrSurfaceProxy> asSurfaceProxyRef() override { return fRenderTargetProxy; }
 
     GrTextureProxy* asTextureProxy() override;
+    const GrTextureProxy* asTextureProxy() const override;
     sk_sp<GrTextureProxy> asTextureProxyRef() override;
 
     GrRenderTargetProxy* asRenderTargetProxy() override { return fRenderTargetProxy.get(); }
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index 77a3e52..9453ce8 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -52,11 +52,12 @@
     static constexpr GrSurfaceFlags kFlags = kRenderTarget_GrSurfaceFlag;
 
     if (!this->instantiateImpl(resourceProvider, fSampleCnt, fNeedsStencil, kFlags,
-                               /* isMipped = */ false,
+                               GrMipMapped::kNo,
                                SkDestinationSurfaceColorMode::kLegacy, nullptr)) {
         return false;
     }
     SkASSERT(fTarget->asRenderTarget());
+    SkASSERT(!fTarget->asTexture());
     // Check that our a priori computation matched the ultimate reality
     SkASSERT(fRenderTargetFlags == fTarget->asRenderTarget()->renderTargetPriv().flags());
 
@@ -67,12 +68,13 @@
     static constexpr GrSurfaceFlags kFlags = kRenderTarget_GrSurfaceFlag;
 
     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt, fNeedsStencil,
-                                                       kFlags, /* isMipped = */ false,
+                                                       kFlags, GrMipMapped::kNo,
                                                        SkDestinationSurfaceColorMode::kLegacy);
     if (!surface) {
         return nullptr;
     }
     SkASSERT(surface->asRenderTarget());
+    SkASSERT(!surface->asTexture());
     // Check that our a priori computation matched the ultimate reality
     SkASSERT(fRenderTargetFlags == surface->asRenderTarget()->renderTargetPriv().flags());
 
@@ -81,8 +83,9 @@
 
 size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
     int colorSamplesPerPixel = this->numColorSamples() + 1;
+
     // TODO: do we have enough information to improve this worst case estimate?
-    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, false,
+    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, GrMipMapped::kNo,
                                   SkBackingFit::kApprox == fFit);
 }
 
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index b97980f..24b42f3 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -51,7 +51,7 @@
                               int width,
                               int height,
                               int colorSamplesPerPixel,
-                              bool hasMIPMaps,
+                              GrMipMapped mipMapped,
                               bool useNextPow2) {
     width = useNextPow2 ? GrNextPow2(width) : width;
     height = useNextPow2 ? GrNextPow2(height) : height;
@@ -62,7 +62,7 @@
 
     size_t finalSize = colorSamplesPerPixel * colorSize;
 
-    if (hasMIPMaps) {
+    if (GrMipMapped::kYes == mipMapped) {
         // We don't have to worry about the mipmaps being a different size than
         // we'd expect because we never change fDesc.fWidth/fHeight.
         finalSize += colorSize/3;
diff --git a/src/gpu/GrSurfaceContext.h b/src/gpu/GrSurfaceContext.h
index 0589a60..0511fb1 100644
--- a/src/gpu/GrSurfaceContext.h
+++ b/src/gpu/GrSurfaceContext.h
@@ -96,6 +96,7 @@
     virtual sk_sp<GrSurfaceProxy> asSurfaceProxyRef() = 0;
 
     virtual GrTextureProxy* asTextureProxy() = 0;
+    virtual const GrTextureProxy* asTextureProxy() const = 0;
     virtual sk_sp<GrTextureProxy> asTextureProxyRef() = 0;
 
     virtual GrRenderTargetProxy* asRenderTargetProxy() = 0;
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 69d5110..da5bb17 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -62,9 +62,9 @@
 sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(
                                                 GrResourceProvider* resourceProvider,
                                                 int sampleCnt, bool needsStencil,
-                                                GrSurfaceFlags flags, bool isMipMapped,
+                                                GrSurfaceFlags flags, GrMipMapped mipMapped,
                                                 SkDestinationSurfaceColorMode mipColorMode) const {
-    SkASSERT(!isMipMapped);
+    SkASSERT(GrMipMapped::kNo == mipMapped);
     GrSurfaceDesc desc;
     desc.fFlags = flags;
     if (fNeedsClear) {
@@ -108,7 +108,7 @@
 }
 
 bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
-                                     bool needsStencil, GrSurfaceFlags flags, bool isMipMapped,
+                                     bool needsStencil, GrSurfaceFlags flags, GrMipMapped mipMapped,
                                      SkDestinationSurfaceColorMode mipColorMode,
                                      const GrUniqueKey* uniqueKey) {
     if (fTarget) {
@@ -119,7 +119,7 @@
     }
 
     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, needsStencil,
-                                                       flags, isMipMapped, mipColorMode);
+                                                       flags, mipMapped, mipColorMode);
     if (!surface) {
         return false;
     }
@@ -142,16 +142,16 @@
     }
 
     const GrTextureProxy* tp = this->asTextureProxy();
-    bool hasMipMaps = false;
+    GrMipMapped mipMapped = GrMipMapped::kNo;
     if (tp) {
-        hasMipMaps = tp->isMipMapped();
+        mipMapped = tp->mipMapped();
     }
 
     int width = this->worstCaseWidth();
     int height = this->worstCaseHeight();
 
     GrTexturePriv::ComputeScratchKey(this->config(), width, height, SkToBool(rtp), sampleCount,
-                                     hasMipMaps, key);
+                                     mipMapped, key);
 }
 
 void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index b0dba51..b4cefb0 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -37,7 +37,7 @@
 
 size_t GrTexture::onGpuMemorySize() const {
     return GrSurface::ComputeSize(this->config(), this->width(), this->height(), 1,
-                                  this->texturePriv().hasMipMaps(), false);
+                                  this->texturePriv().mipMapped(), false);
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -84,12 +84,12 @@
     }
     GrTexturePriv::ComputeScratchKey(this->config(), this->width(), this->height(),
                                      SkToBool(rt), sampleCount,
-                                     this->texturePriv().hasMipMaps(), key);
+                                     this->texturePriv().mipMapped(), key);
 }
 
 void GrTexturePriv::ComputeScratchKey(GrPixelConfig config, int width, int height,
                                       bool isRenderTarget, int sampleCnt,
-                                      bool isMipMapped, GrScratchKey* key) {
+                                      GrMipMapped mipMapped, GrScratchKey* key) {
     static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
     uint32_t flags = isRenderTarget;
 
@@ -100,16 +100,17 @@
     SkASSERT(static_cast<int>(config) < (1 << 5));
     SkASSERT(sampleCnt < (1 << 8));
     SkASSERT(flags < (1 << 10));
+    SkASSERT(static_cast<int>(mipMapped) <= 1);
 
     GrScratchKey::Builder builder(key, kType, 3);
     builder[0] = width;
     builder[1] = height;
-    builder[2] = config | (isMipMapped << 5) | (sampleCnt << 6) | (flags << 14);
+    builder[2] = config | (static_cast<uint8_t>(mipMapped) << 5) | (sampleCnt << 6) | (flags << 14);
 }
 
 void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) {
     // Note: the fOrigin field is not used in the scratch key
     return ComputeScratchKey(desc.fConfig, desc.fWidth, desc.fHeight,
                              SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag), desc.fSampleCnt,
-                             false, key);
+                             GrMipMapped::kNo, key);
 }
diff --git a/src/gpu/GrTextureContext.h b/src/gpu/GrTextureContext.h
index f59ab1a..f083e71 100644
--- a/src/gpu/GrTextureContext.h
+++ b/src/gpu/GrTextureContext.h
@@ -32,6 +32,7 @@
     sk_sp<GrSurfaceProxy> asSurfaceProxyRef() override { return fTextureProxy; }
 
     GrTextureProxy* asTextureProxy() override { return fTextureProxy.get(); }
+    const GrTextureProxy* asTextureProxy() const override { return fTextureProxy.get(); }
     sk_sp<GrTextureProxy> asTextureProxyRef() override { return fTextureProxy; }
 
     GrRenderTargetProxy* asRenderTargetProxy() override;
diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h
index 31d097ed..fc474ed 100644
--- a/src/gpu/GrTexturePriv.h
+++ b/src/gpu/GrTexturePriv.h
@@ -29,8 +29,11 @@
         return GrMipMapsStatus::kValid != fTexture->fMipMapsStatus;
     }
 
-    bool hasMipMaps() const {
-        return GrMipMapsStatus::kNotAllocated != fTexture->fMipMapsStatus;
+    GrMipMapped mipMapped() const {
+        if (GrMipMapsStatus::kNotAllocated != fTexture->fMipMapsStatus) {
+            return GrMipMapped::kYes;
+        }
+        return GrMipMapped::kNo;
     }
 
     void setMaxMipMapLevel(int maxMipMapLevel) const {
@@ -62,7 +65,7 @@
     static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*);
     static void ComputeScratchKey(GrPixelConfig config, int width, int height,
                                   bool isRenderTarget, int sampleCnt,
-                                  bool isMipMapped, GrScratchKey* key);
+                                  GrMipMapped, GrScratchKey* key);
 
 
 private:
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index 534adaa..4617285 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -16,7 +16,7 @@
 GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, SkBudgeted budgeted,
                                const void* srcData, size_t /*rowBytes*/, uint32_t flags)
         : INHERITED(srcDesc, fit, budgeted, flags)
-        , fIsMipMapped(false)
+        , fMipMapped(GrMipMapped::kNo)
         , fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
         , fCache(nullptr)
         , fDeferredUploader(nullptr) {
@@ -25,7 +25,7 @@
 
 GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, GrSurfaceOrigin origin)
         : INHERITED(std::move(surf), origin, SkBackingFit::kExact)
-        , fIsMipMapped(fTarget->asTexture()->texturePriv().hasMipMaps())
+        , fMipMapped(fTarget->asTexture()->texturePriv().mipMapped())
         , fMipColorMode(fTarget->asTexture()->texturePriv().mipColorMode())
         , fCache(nullptr)
         , fDeferredUploader(nullptr) {
@@ -48,11 +48,12 @@
 
 bool GrTextureProxy::instantiate(GrResourceProvider* resourceProvider) {
     if (!this->instantiateImpl(resourceProvider, 0, /* needsStencil = */ false,
-                               kNone_GrSurfaceFlags, fIsMipMapped, fMipColorMode,
+                               kNone_GrSurfaceFlags, fMipMapped, fMipColorMode,
                                fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
         return false;
     }
 
+    SkASSERT(!fTarget->asRenderTarget());
     SkASSERT(fTarget->asTexture());
     return true;
 }
@@ -61,11 +62,12 @@
     sk_sp<GrSurface> surface= this->createSurfaceImpl(resourceProvider, 0,
                                                       /* needsStencil = */ false,
                                                       kNone_GrSurfaceFlags,
-                                                      fIsMipMapped, fMipColorMode);
+                                                      fMipMapped, fMipColorMode);
     if (!surface) {
         return nullptr;
     }
 
+    SkASSERT(!surface->asRenderTarget());
     SkASSERT(surface->asTexture());
     return surface;
 }
@@ -107,10 +109,9 @@
 }
 
 size_t GrTextureProxy::onUninstantiatedGpuMemorySize() const {
-    static const bool kHasMipMaps = true;
     // TODO: add tracking of mipmap state to improve the estimate. We track whether we are created
     // with mip maps but not whether a texture read from the proxy will lazily generate mip maps.
-    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, 1, kHasMipMaps,
+    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, 1, GrMipMapped::kYes,
                                   SkBackingFit::kApprox == fFit);
 }
 
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index 7515c3d..7d4040e 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -36,12 +36,11 @@
 size_t GrTextureRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
     int colorSamplesPerPixel = this->numColorSamples() + 1;
 
-    static const bool kHasMipMaps = true;
     // TODO: add tracking of mipmap state to improve the estimate. We track whether we are created
     // with mip maps but not whether a texture read from the proxy will lazily generate mip maps.
 
     // TODO: do we have enough information to improve this worst case estimate?
-    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, kHasMipMaps,
+    return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, GrMipMapped::kYes,
                                   SkBackingFit::kApprox == fFit);
 }
 
@@ -51,7 +50,7 @@
     const GrUniqueKey& key = this->getUniqueKey();
 
     if (!this->instantiateImpl(resourceProvider, this->numStencilSamples(), this->needsStencil(),
-                               kFlags, this->isMipMapped(), this->mipColorMode(),
+                               kFlags, this->mipMapped(), this->mipColorMode(),
                                key.isValid() ? &key : nullptr)) {
         return false;
     }
@@ -71,7 +70,7 @@
 
     sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, this->numStencilSamples(),
                                                        this->needsStencil(), kFlags,
-                                                       this->isMipMapped(), this->mipColorMode());
+                                                       this->mipMapped(), this->mipColorMode());
     if (!surface) {
         return nullptr;
     }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 4a1ec82..eb9e8e8 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -97,8 +97,8 @@
 
 sk_sp<SkGpuDevice> SkGpuDevice::Make(GrContext* context, SkBudgeted budgeted,
                                      const SkImageInfo& info, int sampleCount,
-                                     GrSurfaceOrigin origin,
-                                     const SkSurfaceProps* props, InitContents init) {
+                                     GrSurfaceOrigin origin, const SkSurfaceProps* props,
+                                     GrMipMapped mipMapped, InitContents init) {
     unsigned flags;
     if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
         return nullptr;
@@ -106,7 +106,8 @@
 
     sk_sp<GrRenderTargetContext> renderTargetContext(MakeRenderTargetContext(context, budgeted,
                                                                              info, sampleCount,
-                                                                             origin, props));
+                                                                             origin, props,
+                                                                             mipMapped));
     if (!renderTargetContext) {
         return nullptr;
     }
@@ -146,7 +147,8 @@
                                                                const SkImageInfo& origInfo,
                                                                int sampleCount,
                                                                GrSurfaceOrigin origin,
-                                                               const SkSurfaceProps* surfaceProps) {
+                                                               const SkSurfaceProps* surfaceProps,
+                                                               GrMipMapped mipMapped) {
     if (kUnknown_SkColorType == origInfo.colorType() ||
         origInfo.width() < 0 || origInfo.height() < 0) {
         return nullptr;
@@ -246,7 +248,8 @@
                                                             this->imageInfo(),
                                                             fRenderTargetContext->numColorSamples(),
                                                             fRenderTargetContext->origin(),
-                                                            &this->surfaceProps()));
+                                                            &this->surfaceProps(),
+                                                            fRenderTargetContext->mipMapped()));
     if (!newRTC) {
         return;
     }
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 548819b..79e5991 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -46,14 +46,15 @@
 
     /**
      * New device that will create an offscreen renderTarget based on the ImageInfo and
-     * sampleCount. The Budgeted param controls whether the device's backing store counts against
-     * the resource cache budget. On failure, returns nullptr.
+     * sampleCount. The mipMapped flag tells the gpu to create the underlying render target with
+     * mips. The Budgeted param controls whether the device's backing store counts against the
+     * resource cache budget. On failure, returns nullptr.
      * This entry point creates a kExact backing store. It is used when creating SkGpuDevices
      * for SkSurfaces.
      */
     static sk_sp<SkGpuDevice> Make(GrContext*, SkBudgeted, const SkImageInfo&,
-                                   int sampleCount, GrSurfaceOrigin,
-                                   const SkSurfaceProps*, InitContents);
+                                   int sampleCount, GrSurfaceOrigin, const SkSurfaceProps*,
+                                   GrMipMapped mipMapped, InitContents);
 
     ~SkGpuDevice() override {}
 
@@ -260,7 +261,8 @@
                                                                 const SkImageInfo&,
                                                                 int sampleCount,
                                                                 GrSurfaceOrigin,
-                                                                const SkSurfaceProps*);
+                                                                const SkSurfaceProps*,
+                                                                GrMipMapped);
 
     friend class GrAtlasTextContext;
     friend class SkSurface_Gpu;      // for access to surfaceProps
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index 140ee2b..3aa632c 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -84,7 +84,7 @@
 
 size_t GrGLRenderTarget::onGpuMemorySize() const {
     return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
-                                  fNumSamplesOwnedPerPixel, false);
+                                  fNumSamplesOwnedPerPixel, GrMipMapped::kNo);
 }
 
 bool GrGLRenderTarget::completeStencilAttachment() {
@@ -190,7 +190,7 @@
     // (have a fMSColorRenderbufferID).
     if (fMSColorRenderbufferID) {
         size_t size = GrSurface::ComputeSize(this->config(), this->width(), this->height(),
-                                             this->msaaSamples(), false);
+                                             this->msaaSamples(), GrMipMapped::kNo);
 
         // Due to this resource having both a texture and a renderbuffer component, dump as
         // skia/gpu_resources/resource_#/renderbuffer
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index c4a0456..3e7b89f 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -81,5 +81,5 @@
 size_t GrGLTextureRenderTarget::onGpuMemorySize() const {
     return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
                                     this->numSamplesOwnedPerPixel(),
-                                    this->texturePriv().hasMipMaps());
+                                    this->texturePriv().mipMapped());
 }
diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h
index 44ca320..0469d4f 100644
--- a/src/gpu/mock/GrMockTexture.h
+++ b/src/gpu/mock/GrMockTexture.h
@@ -89,13 +89,13 @@
     size_t onGpuMemorySize() const override {
         return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
                                       this->numStencilSamples(),
-                                      this->texturePriv().hasMipMaps());
+                                      this->texturePriv().mipMapped());
     }
 
     void computeScratchKey(GrScratchKey* key) const override {
         GrTexturePriv::ComputeScratchKey(this->config(), this->width(), this->height(),
                                          true, this->numStencilSamples(),
-                                         this->texturePriv().hasMipMaps(), key);
+                                         this->texturePriv().mipMapped(), key);
     }
 };
 
diff --git a/src/gpu/mtl/GrMtlRenderTarget.h b/src/gpu/mtl/GrMtlRenderTarget.h
index a53e49d..186f703 100644
--- a/src/gpu/mtl/GrMtlRenderTarget.h
+++ b/src/gpu/mtl/GrMtlRenderTarget.h
@@ -60,7 +60,7 @@
         // The plus 1 is to account for the resolve texture or if not using msaa the RT itself
         int numColorSamples = this->numColorSamples() + 1;
         return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
-                                      numColorSamples, false);
+                                      numColorSamples, GrMipMapped::kNo);
     }
 
     id<MTLTexture> fRenderTexture;
diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h
index 3e3f60a..18a0bd3 100644
--- a/src/gpu/vk/GrVkRenderTarget.h
+++ b/src/gpu/vk/GrVkRenderTarget.h
@@ -101,7 +101,7 @@
         // The plus 1 is to account for the resolve texture or if not using msaa the RT itself
         int numColorSamples = this->numColorSamples() + 1;
         return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
-                                      numColorSamples, false);
+                                      numColorSamples, GrMipMapped::kNo);
     }
 
     void createFramebuffer(GrVkGpu* gpu);
diff --git a/src/gpu/vk/GrVkTextureRenderTarget.cpp b/src/gpu/vk/GrVkTextureRenderTarget.cpp
index 81509a9..9a211e2 100644
--- a/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -266,5 +266,5 @@
     int numColorSamples = this->numColorSamples() + 1;
     return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
                                   numColorSamples,  // TODO: this still correct?
-                                  this->texturePriv().hasMipMaps());
+                                  this->texturePriv().mipMapped());
 }
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 8e055f3..b18b17a 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -701,7 +701,8 @@
     if (key.isValid()) {
         SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
         if (originalProxy) {
-            SkASSERT(proxy->isMipMapped() && !originalProxy->isMipMapped());
+            SkASSERT(GrMipMapped::kYes == proxy->mipMapped() &&
+                     GrMipMapped::kNo == originalProxy->mipMapped());
             // If we had an originalProxy, that means there already is a proxy in the cache which
             // matches the key, but it does not have mip levels and we require them. Thus we must
             // remove the unique key from that proxy.
@@ -768,7 +769,7 @@
         if (proxy) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kPreExisting_LockTexturePath,
                                      kLockTexturePathCount);
-            if (!willBeMipped || proxy->isMipMapped()) {
+            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 return proxy;
             }
         }
@@ -793,7 +794,7 @@
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
                                      kLockTexturePathCount);
             set_key_on_proxy(ctx->resourceProvider(), proxy.get(), nullptr, key);
-            if (!willBeMipped || proxy->isMipMapped()) {
+            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 return proxy;
             }
         }
@@ -833,7 +834,7 @@
         if (!proxy) {
             proxy = GrUploadBitmapToTextureProxy(ctx->resourceProvider(), bitmap, dstColorSpace);
         }
-        if (proxy && (!willBeMipped || proxy->isMipMapped())) {
+        if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kRGBA_LockTexturePath,
                                      kLockTexturePathCount);
             set_key_on_proxy(ctx->resourceProvider(), proxy.get(), nullptr, key);
@@ -847,7 +848,7 @@
         // mipped surface and copy the original proxy into the base layer. We will then let the gpu
         // generate the rest of the mips.
         SkASSERT(willBeMipped);
-        SkASSERT(!proxy->isMipMapped());
+        SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
         if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(ctx, proxy.get())) {
             set_key_on_proxy(ctx->resourceProvider(), mippedProxy.get(), proxy.get(), key);
             return mippedProxy;
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 1de7b60..04e16f6 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -248,7 +248,7 @@
 #if !SK_SUPPORT_GPU
 
 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
-                                             int, GrSurfaceOrigin, const SkSurfaceProps*) {
+                                             int, GrSurfaceOrigin, const SkSurfaceProps*, bool) {
     return nullptr;
 }
 
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 042fc32..0f90232 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -223,13 +223,17 @@
 
 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted,
                                              const SkImageInfo& info, int sampleCount,
-                                             GrSurfaceOrigin origin, const SkSurfaceProps* props) {
+                                             GrSurfaceOrigin origin, const SkSurfaceProps* props,
+                                             bool shouldCreateWithMips) {
     if (!SkSurface_Gpu::Valid(info)) {
         return nullptr;
     }
 
+    GrMipMapped mipMapped = shouldCreateWithMips ? GrMipMapped::kYes : GrMipMapped::kNo;
+
     sk_sp<SkGpuDevice> device(SkGpuDevice::Make(
-            ctx, budgeted, info, sampleCount, origin, props, SkGpuDevice::kClear_InitContents));
+            ctx, budgeted, info, sampleCount, origin, props, mipMapped,
+            SkGpuDevice::kClear_InitContents));
     if (!device) {
         return nullptr;
     }
diff --git a/tests/DeviceTest.cpp b/tests/DeviceTest.cpp
index 55c9421..64b83fc 100644
--- a/tests/DeviceTest.cpp
+++ b/tests/DeviceTest.cpp
@@ -82,6 +82,7 @@
 
     sk_sp<SkBaseDevice> gpuDev(SkGpuDevice::Make(context, SkBudgeted::kNo, ii,
                                                  0, kBottomLeft_GrSurfaceOrigin, nullptr,
+                                                 GrMipMapped::kNo,
                                                  SkGpuDevice::kClear_InitContents));
 
     SkBitmap bm;
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index 143e902..aad3b60 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -86,14 +86,14 @@
             }
 
             if (GrMipMapped::kYes == mipMapped) {
-                REPORTER_ASSERT(reporter, texture->texturePriv().hasMipMaps());
+                REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
                 if (isRT) {
                     REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
                 } else {
                     REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
                 }
             } else {
-                REPORTER_ASSERT(reporter, !texture->texturePriv().hasMipMaps());
+                REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
             }
             context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
         }
diff --git a/tests/GrTextureMipMapInvalidationTest.cpp b/tests/GrTextureMipMapInvalidationTest.cpp
index 8b2d95f..cfb6853 100644
--- a/tests/GrTextureMipMapInvalidationTest.cpp
+++ b/tests/GrTextureMipMapInvalidationTest.cpp
@@ -19,7 +19,8 @@
 // Tests that MIP maps are created and invalidated as expected when drawing to and from GrTextures.
 DEF_GPUTEST_FOR_NULLGL_CONTEXT(GrTextureMipMapInvalidationTest, reporter, ctxInfo) {
     auto isMipped = [] (SkSurface* surf) {
-        return surf->makeImageSnapshot()->getTexture()->texturePriv().hasMipMaps();
+        const GrTexture* texture = surf->makeImageSnapshot()->getTexture();
+        return GrMipMapped::kYes == texture->texturePriv().mipMapped();
     };
 
     auto mipsAreDirty = [] (SkSurface* surf) {