Move GrBackendRenderTarget over to new system of getting backed infos

Bug: skia:
Change-Id: I3927390894715e8424b3d0240dad3ee6cd03dc38
Reviewed-on: https://skia-review.googlesource.com/120181
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h
index f0bbab5..2fe3309 100644
--- a/include/gpu/GrBackendSurface.h
+++ b/include/gpu/GrBackendSurface.h
@@ -155,11 +155,13 @@
     bool getGLTextureInfo(GrGLTextureInfo*) const;
 
 #ifdef SK_VULKAN
-    // If the backend API is Vulkan, copies a snapshot of the GrGLImageInfo struct into the passed
+    // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
     // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
     // state. Otherwise returns false if the backend API is not Vulkan.
     bool getVkImageInfo(GrVkImageInfo*) const;
 
+    // Anytime the client changes the VkImageLayout of the VkImage captured by this
+    // GrBackendTexture, they must call this function to notify Skia of the changed layout.
     void setVkImageLayout(VkImageLayout);
 #endif
 
@@ -263,23 +265,35 @@
                           int stencilBits,
                           const GrMockRenderTargetInfo& mockInfo);
 
+    ~GrBackendRenderTarget();
+
+    GrBackendRenderTarget(const GrBackendRenderTarget& that);
+    GrBackendRenderTarget& operator=(const GrBackendRenderTarget&);
+
     int width() const { return fWidth; }
     int height() const { return fHeight; }
     int sampleCnt() const { return fSampleCnt; }
     int stencilBits() const { return fStencilBits; }
     GrBackend backend() const {return fBackend; }
 
-    // If the backend API is GL, this returns a pointer to the GrGLFramebufferInfo struct. Otherwise
-    // it returns nullptr.
-    const GrGLFramebufferInfo* getGLFramebufferInfo() const;
+    // If the backend API is GL, copies a snapshot of the GrGLFramebufferInfo struct into the passed
+    // in pointer and returns true. Otherwise returns false if the backend API is not GL.
+    bool getGLFramebufferInfo(GrGLFramebufferInfo*) const;
 
 #ifdef SK_VULKAN
-    // If the backend API is Vulkan, this returns a pointer to the GrVkImageInfo struct. Otherwise
-    // it returns nullptr
-    const GrVkImageInfo* getVkImageInfo() const;
+    // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
+    // in pointer and returns true. This snapshot will set the fImageLayout to the current layout
+    // state. Otherwise returns false if the backend API is not Vulkan.
+    bool getVkImageInfo(GrVkImageInfo*) const;
+
+    // Anytime the client changes the VkImageLayout of the VkImage captured by this
+    // GrBackendRenderTarget, they must call this function to notify Skia of the changed layout.
+    void setVkImageLayout(VkImageLayout);
 #endif
 
-    const GrMockRenderTargetInfo* getMockRenderTargetInfo() const;
+    // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed
+    // in pointer and returns true. Otherwise returns false if the backend API is not Mock.
+    bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const;
 
     // Returns true if the backend texture has been initialized.
     bool isValid() const { return fIsValid; }
@@ -301,6 +315,18 @@
     friend class GrVkGpu;
     GrPixelConfig config() const { return fConfig; }
 
+#ifdef SK_VULKAN
+   // Requires friending of GrVkGpu (done above already)
+   sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
+
+   friend class GrVkRenderTarget;
+   GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo,
+                         sk_sp<GrVkImageLayout> layout);
+#endif
+
+    // Free and release and resources being held by the GrBackendTexture.
+    void cleanup();
+
     bool fIsValid;
     int fWidth;         //<! width in pixels
     int fHeight;        //<! height in pixels
@@ -314,7 +340,7 @@
     union {
         GrGLFramebufferInfo fGLInfo;
 #ifdef SK_VULKAN
-        GrVkImageInfo   fVkInfo;
+        GrVkBackendSurfaceInfo fVkInfo;
 #endif
         GrMockRenderTargetInfo fMockInfo;
     };
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 36c26e9..eb7aea2 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -301,6 +301,14 @@
                                              int height,
                                              int sampleCnt,
                                              const GrVkImageInfo& vkInfo)
+        : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
+                                sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
+
+GrBackendRenderTarget::GrBackendRenderTarget(int width,
+                                             int height,
+                                             int sampleCnt,
+                                             const GrVkImageInfo& vkInfo,
+                                             sk_sp<GrVkImageLayout> layout)
         : fIsValid(true)
         , fWidth(width)
         , fHeight(height)
@@ -308,7 +316,7 @@
         , fStencilBits(0)  // We always create stencil buffers internally for vulkan
         , fConfig(GrVkFormatToPixelConfig(vkInfo.fFormat))
         , fBackend(kVulkan_GrBackend)
-        , fVkInfo(vkInfo) {}
+        , fVkInfo(vkInfo, layout.release()) {}
 #endif
 
 #if GR_TEST_UTILS
@@ -356,27 +364,95 @@
         , fConfig(mockInfo.fConfig)
         , fMockInfo(mockInfo) {}
 
+GrBackendRenderTarget::~GrBackendRenderTarget() {
+    this->cleanup();
+}
+
+void GrBackendRenderTarget::cleanup() {
 #ifdef SK_VULKAN
-const GrVkImageInfo* GrBackendRenderTarget::getVkImageInfo() const {
-    if (kVulkan_GrBackend == fBackend) {
-        return &fVkInfo;
+    if (this->isValid() && kVulkan_GrBackend == fBackend) {
+        fVkInfo.cleanup();
+    }
+#endif
+}
+
+GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
+    *this = that;
+}
+
+GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTarget& that) {
+    if (!that.isValid()) {
+        this->cleanup();
+        fIsValid = false;
+        return *this;
+    }
+    fWidth = that.fWidth;
+    fHeight = that.fHeight;
+    fSampleCnt = that.fSampleCnt;
+    fStencilBits = that.fStencilBits;
+    fConfig = that.fConfig;
+    fBackend = that.fBackend;
+
+    switch (that.fBackend) {
+        case kOpenGL_GrBackend:
+            fGLInfo = that.fGLInfo;
+            break;
+#ifdef SK_VULKAN
+        case kVulkan_GrBackend:
+            fVkInfo.assign(that.fVkInfo, this->isValid());
+            break;
+#endif
+#ifdef SK_METAL
+        case kMetal_GrBackend:
+            break;
+#endif
+        case kMock_GrBackend:
+            fMockInfo = that.fMockInfo;
+            break;
+        default:
+            SK_ABORT("Unknown GrBackend");
+    }
+    fIsValid = that.fIsValid;
+    return *this;
+}
+
+#ifdef SK_VULKAN
+bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
+    if (this->isValid() && kVulkan_GrBackend == fBackend) {
+        *outInfo = fVkInfo.snapImageInfo();
+        return true;
+    }
+    return false;
+}
+
+void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
+    if (this->isValid() && kVulkan_GrBackend == fBackend) {
+        fVkInfo.setImageLayout(layout);
+    }
+}
+
+sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
+    if (this->isValid() && kVulkan_GrBackend == fBackend) {
+        return fVkInfo.getGrVkImageLayout();
     }
     return nullptr;
 }
 #endif
 
-const GrGLFramebufferInfo* GrBackendRenderTarget::getGLFramebufferInfo() const {
-    if (kOpenGL_GrBackend == fBackend) {
-        return &fGLInfo;
+bool GrBackendRenderTarget::getGLFramebufferInfo(GrGLFramebufferInfo* outInfo) const {
+    if (this->isValid() && kOpenGL_GrBackend == fBackend) {
+        *outInfo = fGLInfo;
+        return true;
     }
-    return nullptr;
+    return false;
 }
 
-const GrMockRenderTargetInfo* GrBackendRenderTarget::getMockRenderTargetInfo() const {
-    if (kMock_GrBackend == fBackend) {
-        return &fMockInfo;
+bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outInfo) const {
+    if (this->isValid() && kMock_GrBackend == fBackend) {
+        *outInfo = fMockInfo;
+        return true;
     }
-    return nullptr;
+    return false;
 }
 
 #if GR_TEST_UTILS
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 990a15d..b8ddebc 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -2561,10 +2561,10 @@
 }
 
 bool GrGLCaps::onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget& backendRT) const {
-    const GrGLFramebufferInfo* fbInfo = backendRT.getGLFramebufferInfo();
-    SkASSERT(fbInfo);
+    GrGLFramebufferInfo fbInfo;
+    SkAssertResult(backendRT.getGLFramebufferInfo(&fbInfo));
     // Window Rectangles are not supported for FBO 0;
-    return fbInfo->fFBOID != 0;
+    return fbInfo.fFBOID != 0;
 }
 
 int GrGLCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
@@ -2678,11 +2678,11 @@
 
 bool GrGLCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt, SkColorType ct,
                                            GrPixelConfig* config) const {
-    const GrGLFramebufferInfo* fbInfo = rt.getGLFramebufferInfo();
-    if (!fbInfo) {
+    GrGLFramebufferInfo fbInfo;
+    if (!rt.getGLFramebufferInfo(&fbInfo)) {
         return false;
     }
-    return validate_sized_format(fbInfo->fFormat, ct, config, fStandard);
+    return validate_sized_format(fbInfo.fFormat, ct, config, fStandard);
 }
 
 bool GrGLCaps::getConfigFromBackendFormat(const GrBackendFormat& format, SkColorType ct,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index c9cd494..e162d83 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -593,13 +593,13 @@
 }
 
 sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
-    const GrGLFramebufferInfo* info = backendRT.getGLFramebufferInfo();
-    if (!info) {
+    GrGLFramebufferInfo info;
+    if (!backendRT.getGLFramebufferInfo(&info)) {
         return nullptr;
     }
 
     GrGLRenderTarget::IDDesc idDesc;
-    idDesc.fRTFBOID = info->fFBOID;
+    idDesc.fRTFBOID = info.fFBOID;
     idDesc.fMSColorRenderbufferID = 0;
     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
     idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
@@ -4500,9 +4500,10 @@
 
 void GrGLGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
     SkASSERT(kOpenGL_GrBackend == backendRT.backend());
-    if (auto info = backendRT.getGLFramebufferInfo()) {
-        if (info->fFBOID) {
-            GL_CALL(DeleteFramebuffers(1, &info->fFBOID));
+    GrGLFramebufferInfo info;
+    if (backendRT.getGLFramebufferInfo(&info)) {
+        if (info.fFBOID) {
+            GL_CALL(DeleteFramebuffers(1, &info.fFBOID));
         }
     }
 }
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index 060d7bd..0d4cf62 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -136,8 +136,9 @@
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
     desc.fWidth = rt.width();
     desc.fHeight = rt.height();
-    SkASSERT(rt.getMockRenderTargetInfo());
-    const GrMockRenderTargetInfo info = *rt.getMockRenderTargetInfo();
+
+    GrMockRenderTargetInfo info;
+    SkAssertResult(rt.getMockRenderTargetInfo(&info));
     desc.fConfig = info.fConfig;
 
     return sk_sp<GrRenderTarget>(
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 5747cc0..ae1570c 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -510,12 +510,12 @@
 
 bool GrVkCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt, SkColorType ct,
                                            GrPixelConfig* config) const {
-    const GrVkImageInfo* imageInfo = rt.getVkImageInfo();
-    if (!imageInfo) {
+    GrVkImageInfo imageInfo;
+    if (!rt.getVkImageInfo(&imageInfo)) {
         return false;
     }
 
-    return validate_image_info(imageInfo->fFormat, ct, config);
+    return validate_image_info(imageInfo.fFormat, ct, config);
 }
 
 bool GrVkCaps::getConfigFromBackendFormat(const GrBackendFormat& format, SkColorType ct,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 0d45ae0..3b1b219 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -933,11 +933,12 @@
         return nullptr;
     }
 
-    const GrVkImageInfo* info = backendRT.getVkImageInfo();
-    if (!info) {
+    GrVkImageInfo info;
+    if (!backendRT.getVkImageInfo(&info)) {
         return nullptr;
     }
-    if (VK_NULL_HANDLE == info->fImage) {
+
+    if (VK_NULL_HANDLE == info.fImage) {
         return nullptr;
     }
 
@@ -948,9 +949,9 @@
     desc.fConfig = backendRT.config();
     desc.fSampleCnt = 1;
 
-    sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info->fImageLayout));
+    sk_sp<GrVkImageLayout> layout = backendRT.getGrVkImageLayout();
 
-    sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, *info,
+    sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info,
                                                                             std::move(layout));
 
     // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
@@ -1565,10 +1566,11 @@
 void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
     SkASSERT(kVulkan_GrBackend == rt.fBackend);
 
-    if (const auto* info = rt.getVkImageInfo()) {
+    GrVkImageInfo info;
+    if (rt.getVkImageInfo(&info)) {
         // something in the command buffer may still be using this, so force submit
         this->submitCommandBuffer(kForce_SyncQueue);
-        GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(info));
+        GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(&info));
     }
 }
 
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index 5570c0d..83c3b97 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -360,12 +360,8 @@
 }
 
 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
-    int numStencilBits = 0;
-    if (GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment()) {
-        numStencilBits = stencil->bits();
-    }
     return GrBackendRenderTarget(this->width(), this->height(), this->numColorSamples(),
-                                 numStencilBits, fInfo);
+                                 fInfo, this->grVkImageLayout());
 }
 
 const GrVkResource* GrVkRenderTarget::stencilImageResource() const {