Have GrContext abandoned call also check if the underlying device is lost.

Change-Id: Iba09b8f39138e99cbd987880b2da07fdec799248
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/280638
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 832f9eb..fee9b36 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -137,9 +137,12 @@
     void abandonContext() override;
 
     /**
-     * Returns true if the context was abandoned.
+     * Returns true if the context was abandoned or if the if the backend specific context has
+     * gotten into an unrecoverarble, lost state (e.g. in Vulkan backend if we've gotten a
+     * VK_ERROR_DEVICE_LOST). If the backend context is lost, this call will also abandon the
+     * GrContext.
      */
-    using GrImageContext::abandoned;
+    bool abandoned() override;
 
     /**
      * This is similar to abandonContext() however the underlying 3D context is not yet lost and
diff --git a/include/private/GrImageContext.h b/include/private/GrImageContext.h
index c9b869c..9dc0acb 100644
--- a/include/private/GrImageContext.h
+++ b/include/private/GrImageContext.h
@@ -32,7 +32,7 @@
     GrImageContext(GrBackendApi, const GrContextOptions&, uint32_t contextID);
 
     SK_API virtual void abandonContext();
-    SK_API bool abandoned() const;
+    SK_API virtual bool abandoned();
 
     GrProxyProvider* proxyProvider() { return fProxyProvider.get(); }
     const GrProxyProvider* proxyProvider() const { return fProxyProvider.get(); }
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index deda9e3..343bb9d 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -111,7 +111,7 @@
 //////////////////////////////////////////////////////////////////////////////
 
 void GrContext::abandonContext() {
-    if (this->abandoned()) {
+    if (INHERITED::abandoned()) {
         return;
     }
 
@@ -135,7 +135,7 @@
 }
 
 void GrContext::releaseResourcesAndAbandonContext() {
-    if (this->abandoned()) {
+    if (INHERITED::abandoned()) {
         return;
     }
 
@@ -155,6 +155,18 @@
     fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
 }
 
+bool GrContext::abandoned() {
+    if (INHERITED::abandoned()) {
+        return true;
+    }
+
+    if (fGpu && fGpu->isDeviceLost()) {
+        this->abandonContext();
+        return true;
+    }
+    return false;
+}
+
 void GrContext::resetGLTextureBindings() {
     if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
         return;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index e8765d2..3c4cc78 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -68,6 +68,10 @@
     // before GrContext.
     virtual void disconnect(DisconnectType);
 
+    // Called by GrContext::isContextLost. Returns true if the backend Gpu object has gotten into an
+    // unrecoverable, lost state.
+    virtual bool isDeviceLost() const { return false; }
+
     /**
      * The GrGpu object normally assumes that no outsider is setting state
      * within the underlying 3D API's context/device/whatever. This call informs
diff --git a/src/gpu/GrImageContext.cpp b/src/gpu/GrImageContext.cpp
index 5e37c72..3f22c1e 100644
--- a/src/gpu/GrImageContext.cpp
+++ b/src/gpu/GrImageContext.cpp
@@ -31,7 +31,7 @@
     fAbandoned = true;
 }
 
-bool GrImageContext::abandoned() const {
+bool GrImageContext::abandoned() {
     ASSERT_SINGLE_OWNER
 
     return fAbandoned;
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 141068f..1312293 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -48,7 +48,7 @@
     const GrVkInterface* vkInterface() const { return fInterface.get(); }
     const GrVkCaps& vkCaps() const { return *fVkCaps; }
 
-    bool isDeviceLost() const { return fDeviceIsLost; }
+    bool isDeviceLost() const override { return fDeviceIsLost; }
     void setDeviceLost() { fDeviceIsLost = true; }
 
     GrVkMemoryAllocator* memoryAllocator() const { return fMemoryAllocator.get(); }