Switch GrTextureFreedMessages over to using DirectContextIDs

Bug: skia:11728
Change-Id: I514f917577a4166c2834f72fc8c64ab85b259938
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/382879
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index 620e18c..078593f 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -23,37 +23,38 @@
 #include "src/gpu/SkGr.h"
 #include "src/gpu/gl/GrGLTexture.h"
 
-GrBackendTextureImageGenerator::RefHelper::RefHelper(GrTexture* texture, uint32_t owningContextID,
-                                                     std::unique_ptr<GrSemaphore> semaphore)
+GrBackendTextureImageGenerator::RefHelper::RefHelper(
+                    GrTexture* texture,
+                    GrDirectContext::DirectContextID owningContextID,
+                    std::unique_ptr<GrSemaphore> semaphore)
         : fOriginalTexture(texture)
         , fOwningContextID(owningContextID)
         , fBorrowingContextReleaseProc(nullptr)
-        , fBorrowingContextID(SK_InvalidGenID)
         , fSemaphore(std::move(semaphore)) {}
 
 GrBackendTextureImageGenerator::RefHelper::~RefHelper() {
-    SkASSERT(fBorrowingContextID == SK_InvalidUniqueID);
+    SkASSERT(!fBorrowingContextID.isValid());
 
     // Generator has been freed, and no one is borrowing the texture. Notify the original cache
     // that it can free the last ref, so it happens on the correct thread.
     GrTextureFreedMessage msg { fOriginalTexture, fOwningContextID };
-    SkMessageBus<GrTextureFreedMessage, uint32_t>::Post(msg);
+    SkMessageBus<GrTextureFreedMessage, GrDirectContext::DirectContextID>::Post(msg);
 }
 
 std::unique_ptr<SkImageGenerator>
 GrBackendTextureImageGenerator::Make(sk_sp<GrTexture> texture, GrSurfaceOrigin origin,
                                      std::unique_ptr<GrSemaphore> semaphore, SkColorType colorType,
                                      SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
-    GrDirectContext* context = texture->getContext();
+    GrDirectContext* dContext = texture->getContext();
 
     // Attach our texture to this context's resource cache. This ensures that deletion will happen
     // in the correct thread/context. This adds the only ref to the texture that will persist from
     // this point. That ref will be released when the generator's RefHelper is freed.
-    context->priv().getResourceCache()->insertDelayedTextureUnref(texture.get());
+    dContext->priv().getResourceCache()->insertDelayedTextureUnref(texture.get());
 
     GrBackendTexture backendTexture = texture->getBackendTexture();
 
-    if (!context->priv().caps()->areColorTypeAndFormatCompatible(
+    if (!dContext->priv().caps()->areColorTypeAndFormatCompatible(
             SkColorTypeToGrColorType(colorType), backendTexture.getBackendFormat())) {
         return nullptr;
     }
@@ -61,17 +62,17 @@
     SkImageInfo info = SkImageInfo::Make(texture->width(), texture->height(), colorType, alphaType,
                                          std::move(colorSpace));
     return std::unique_ptr<SkImageGenerator>(new GrBackendTextureImageGenerator(
-          info, texture.get(), origin, context->priv().contextID(),
+          info, texture.get(), origin, dContext->directContextID(),
           std::move(semaphore), backendTexture));
 }
 
 GrBackendTextureImageGenerator::GrBackendTextureImageGenerator(
-        const SkImageInfo& info,
-        GrTexture* texture,
-        GrSurfaceOrigin origin,
-        uint32_t owningContextID,
-        std::unique_ptr<GrSemaphore> semaphore,
-        const GrBackendTexture& backendTex)
+                    const SkImageInfo& info,
+                    GrTexture* texture,
+                    GrSurfaceOrigin origin,
+                    GrDirectContext::DirectContextID owningContextID,
+                    std::unique_ptr<GrSemaphore> semaphore,
+                    const GrBackendTexture& backendTex)
         : INHERITED(info)
         , fRefHelper(new RefHelper(texture, owningContextID, std::move(semaphore)))
         , fBackendTexture(backendTex)
@@ -88,33 +89,42 @@
     SkASSERT(refHelper);
 
     refHelper->fBorrowingContextReleaseProc = nullptr;
-    refHelper->fBorrowingContextID = SK_InvalidGenID;
+    refHelper->fBorrowingContextID.makeInvalid();
     refHelper->unref();
 }
 
 GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(
-        GrRecordingContext* context,
+        GrRecordingContext* rContext,
         const SkImageInfo& info,
         const SkIPoint& origin,
         GrMipmapped mipMapped,
         GrImageTexGenPolicy texGenPolicy) {
-    SkASSERT(context);
+    SkASSERT(rContext);
 
-    if (context->backend() != fBackendTexture.backend()) {
+    // We currently limit GrBackendTextureImageGenerators to direct contexts since
+    // only Flutter uses them and doesn't use recording/DDL contexts. Ideally, the
+    // cross context texture functionality can be subsumed by the thread-safe cache
+    // working with utility contexts.
+    auto dContext = rContext->asDirectContext();
+    if (!dContext) {
+        return {};
+    }
+
+    if (dContext->backend() != fBackendTexture.backend()) {
         return {};
     }
     if (info.colorType() != this->getInfo().colorType()) {
         return {};
     }
 
-    auto proxyProvider = context->priv().proxyProvider();
+    auto proxyProvider = dContext->priv().proxyProvider();
 
     fBorrowingMutex.acquire();
     sk_sp<GrRefCntedCallback> releaseProcHelper;
-    if (SK_InvalidGenID != fRefHelper->fBorrowingContextID) {
-        if (fRefHelper->fBorrowingContextID != context->priv().contextID()) {
+    if (fRefHelper->fBorrowingContextID.isValid()) {
+        if (fRefHelper->fBorrowingContextID != dContext->directContextID()) {
             fBorrowingMutex.release();
-            context->priv().printWarningMessage(
+            rContext->priv().printWarningMessage(
                     "GrBackendTextureImageGenerator: Trying to use texture on two GrContexts!\n");
             return {};
         } else {
@@ -131,7 +141,7 @@
                 GrRefCntedCallback::Make(ReleaseRefHelper_TextureReleaseProc, fRefHelper);
         fRefHelper->fBorrowingContextReleaseProc = releaseProcHelper.get();
     }
-    fRefHelper->fBorrowingContextID = context->priv().contextID();
+    fRefHelper->fBorrowingContextID = dContext->directContextID();
     if (!fRefHelper->fBorrowedTextureKey.isValid()) {
         static const auto kDomain = GrUniqueKey::GenerateDomain();
         GrUniqueKey::Builder builder(&fRefHelper->fBorrowedTextureKey, kDomain, 1);
@@ -139,7 +149,7 @@
     }
     fBorrowingMutex.release();
 
-    SkASSERT(fRefHelper->fBorrowingContextID == context->priv().contextID());
+    SkASSERT(fRefHelper->fBorrowingContextID == dContext->directContextID());
 
     GrBackendFormat backendFormat = fBackendTexture.getBackendFormat();
     SkASSERT(backendFormat.isValid());
@@ -154,7 +164,7 @@
     GrMipmapStatus mipmapStatus = fBackendTexture.hasMipmaps()
             ? GrMipmapStatus::kValid : GrMipmapStatus::kNotAllocated;
 
-    GrSwizzle readSwizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
+    GrSwizzle readSwizzle = dContext->priv().caps()->getReadSwizzle(backendFormat, grColorType);
 
     // Must make copies of member variables to capture in the lambda since this image generator may
     // be deleted before we actually execute the lambda.
@@ -219,7 +229,7 @@
                                       ? SkBudgeted::kNo
                                       : SkBudgeted::kYes;
 
-        auto copy = GrSurfaceProxy::Copy(context,
+        auto copy = GrSurfaceProxy::Copy(dContext,
                                          std::move(proxy),
                                          fSurfaceOrigin,
                                          mipMapped,
diff --git a/src/gpu/GrBackendTextureImageGenerator.h b/src/gpu/GrBackendTextureImageGenerator.h
index cea0f40..72bdc96 100644
--- a/src/gpu/GrBackendTextureImageGenerator.h
+++ b/src/gpu/GrBackendTextureImageGenerator.h
@@ -9,7 +9,7 @@
 
 #include "include/core/SkImageGenerator.h"
 #include "include/gpu/GrBackendSurface.h"
-#include "include/gpu/GrRecordingContext.h"
+#include "include/gpu/GrDirectContext.h"
 #include "include/private/GrResourceKey.h"
 #include "include/private/SkMutex.h"
 #include "src/gpu/GrTexture.h"
@@ -48,33 +48,38 @@
                                          GrMipmapped mipMapped, GrImageTexGenPolicy) override;
 
 private:
-    GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin,
-                                   uint32_t owningContextID, std::unique_ptr<GrSemaphore>,
+    GrBackendTextureImageGenerator(const SkImageInfo& info,
+                                   GrTexture*,
+                                   GrSurfaceOrigin,
+                                   GrDirectContext::DirectContextID owningContextID,
+                                   std::unique_ptr<GrSemaphore>,
                                    const GrBackendTexture&);
 
     static void ReleaseRefHelper_TextureReleaseProc(void* ctx);
 
     class RefHelper : public SkNVRefCnt<RefHelper> {
     public:
-        RefHelper(GrTexture*, uint32_t owningContextID, std::unique_ptr<GrSemaphore>);
+        RefHelper(GrTexture*,
+                  GrDirectContext::DirectContextID owningContextID,
+                  std::unique_ptr<GrSemaphore>);
 
         ~RefHelper();
 
-        GrTexture*                   fOriginalTexture;
-        uint32_t                     fOwningContextID;
+        GrTexture*                       fOriginalTexture;
+        GrDirectContext::DirectContextID fOwningContextID;
 
         // We use this key so that we don't rewrap the GrBackendTexture in a GrTexture for each
         // proxy created from this generator for a particular borrowing context.
-        GrUniqueKey                  fBorrowedTextureKey;
+        GrUniqueKey                      fBorrowedTextureKey;
         // There is no ref associated with this pointer. We rely on our atomic bookkeeping with the
         // context ID to know when this pointer is valid and safe to use. This is used to make sure
         // all uses of the wrapped texture are finished on the borrowing context before we open
         // this back up to other contexts. In general a ref to this release proc is owned by all
         // proxies and gpu uses of the backend texture.
-        GrRefCntedCallback*          fBorrowingContextReleaseProc;
-        uint32_t                     fBorrowingContextID;
+        GrRefCntedCallback*              fBorrowingContextReleaseProc;
+        GrDirectContext::DirectContextID fBorrowingContextID;
 
-        std::unique_ptr<GrSemaphore> fSemaphore;
+        std::unique_ptr<GrSemaphore>     fSemaphore;
     };
 
     RefHelper*       fRefHelper;
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index f04c365..96621c6 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -209,7 +209,9 @@
     SkASSERT(this->threadSafeCache());
 
     fStrikeCache = std::make_unique<GrStrikeCache>();
-    fResourceCache = std::make_unique<GrResourceCache>(this->singleOwner(), this->contextID());
+    fResourceCache = std::make_unique<GrResourceCache>(this->singleOwner(),
+                                                       this->directContextID(),
+                                                       this->contextID());
     fResourceCache->setProxyProvider(this->proxyProvider());
     fResourceCache->setThreadSafeCache(this->threadSafeCache());
     fResourceProvider = std::make_unique<GrResourceProvider>(fGpu.get(), fResourceCache.get(),
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index ac22385..4c5cb85 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -27,7 +27,7 @@
 
 DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage, uint32_t, true);
 
-DECLARE_SKMESSAGEBUS_MESSAGE(GrTextureFreedMessage, uint32_t, true);
+DECLARE_SKMESSAGEBUS_MESSAGE(GrTextureFreedMessage, GrDirectContext::DirectContextID, true);
 
 #define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner)
 
@@ -108,12 +108,16 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-GrResourceCache::GrResourceCache(GrSingleOwner* singleOwner, uint32_t contextUniqueID)
-        : fInvalidUniqueKeyInbox(contextUniqueID)
-        , fFreedTextureInbox(contextUniqueID)
-        , fContextUniqueID(contextUniqueID)
+GrResourceCache::GrResourceCache(GrSingleOwner* singleOwner,
+                                 GrDirectContext::DirectContextID owningContextID,
+                                 uint32_t familyID)
+        : fInvalidUniqueKeyInbox(familyID)
+        , fFreedTextureInbox(owningContextID)
+        , fOwningContextID(owningContextID)
+        , fContextUniqueID(familyID)
         , fSingleOwner(singleOwner) {
-    SkASSERT(contextUniqueID != SK_InvalidUniqueID);
+    SkASSERT(owningContextID.isValid());
+    SkASSERT(familyID != SK_InvalidUniqueID);
 }
 
 GrResourceCache::~GrResourceCache() {
@@ -679,7 +683,7 @@
     SkTArray<GrTextureFreedMessage> msgs;
     fFreedTextureInbox.poll(&msgs);
     for (int i = 0; i < msgs.count(); ++i) {
-        SkASSERT(msgs[i].fOwningUniqueID == fContextUniqueID);
+        SkASSERT(msgs[i].fIntendedRecipient == fOwningContextID);
         uint32_t id = msgs[i].fTexture->uniqueID().asUInt();
         TextureAwaitingUnref* info = fTexturesAwaitingUnref.find(id);
         // If the GrContext was released or abandoned then fTexturesAwaitingUnref should have been
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index e1706a3..4a634ad 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -9,6 +9,7 @@
 #define GrResourceCache_DEFINED
 
 #include "include/core/SkRefCnt.h"
+#include "include/gpu/GrDirectContext.h"
 #include "include/private/GrResourceKey.h"
 #include "include/private/SkTArray.h"
 #include "include/private/SkTHash.h"
@@ -30,13 +31,12 @@
 
 struct GrTextureFreedMessage {
     GrTexture* fTexture;
-    uint32_t fOwningUniqueID;
+    GrDirectContext::DirectContextID fIntendedRecipient;
 };
 
 static inline bool SkShouldPostMessageToBus(
-        const GrTextureFreedMessage& msg, uint32_t msgBusUniqueID) {
-    // The inbox's ID is the unique ID of the owning GrContext.
-    return msgBusUniqueID == msg.fOwningUniqueID;
+        const GrTextureFreedMessage& msg, GrDirectContext::DirectContextID potentialRecipient) {
+    return potentialRecipient == msg.fIntendedRecipient;
 }
 
 /**
@@ -58,7 +58,9 @@
  */
 class GrResourceCache {
 public:
-    GrResourceCache(GrSingleOwner* owner, uint32_t contextUniqueID);
+    GrResourceCache(GrSingleOwner* owner,
+                    GrDirectContext::DirectContextID owningContextID,
+                    uint32_t familyID);
     ~GrResourceCache();
 
     // Default maximum number of bytes of gpu memory of budgeted resources in the cache.
@@ -321,8 +323,10 @@
         return res->cacheAccess().accessCacheIndex();
     }
 
+    using TextureFreedMessageBus = SkMessageBus<GrTextureFreedMessage,
+                                                GrDirectContext::DirectContextID>;
+
     typedef SkMessageBus<GrUniqueKeyInvalidatedMessage, uint32_t>::Inbox InvalidUniqueKeyInbox;
-    typedef SkMessageBus<GrTextureFreedMessage, uint32_t>::Inbox FreedTextureInbox;
     typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
     typedef SkTDArray<GrGpuResource*> ResourceArray;
 
@@ -362,9 +366,10 @@
     int                                 fNumBudgetedResourcesFlushWillMakePurgeable = 0;
 
     InvalidUniqueKeyInbox               fInvalidUniqueKeyInbox;
-    FreedTextureInbox                   fFreedTextureInbox;
+    TextureFreedMessageBus::Inbox       fFreedTextureInbox;
     TexturesAwaitingUnref               fTexturesAwaitingUnref;
 
+    GrDirectContext::DirectContextID    fOwningContextID;
     uint32_t                            fContextUniqueID = SK_InvalidUniqueID;
     GrSingleOwner*                      fSingleOwner = nullptr;
 
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index ecaabbb..0b3ae30 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -259,7 +259,8 @@
             // In the future the GrSurface class hierarchy refactoring should eliminate this
             // difficulty by removing the virtual inheritance.
             if (fTexture) {
-                SkMessageBus<GrTextureFreedMessage, uint32_t>::Post({fTexture, fTextureContextID});
+                GrTextureFreedMessage msg { fTexture, fTextureContextID };
+                SkMessageBus<GrTextureFreedMessage, GrDirectContext::DirectContextID>::Post(msg);
             }
         }
 
@@ -313,7 +314,7 @@
             // our destructor.
             auto dContext = fTexture->getContext();
             dContext->priv().getResourceCache()->insertDelayedTextureUnref(fTexture);
-            fTextureContextID = dContext->priv().contextID();
+            fTextureContextID = dContext->directContextID();
             return {std::move(tex), kReleaseCallbackOnInstantiation, kKeySyncMode};
         }
 
@@ -321,7 +322,7 @@
         PromiseImageTextureFulfillProc fFulfillProc;
         sk_sp<GrRefCntedCallback> fReleaseHelper;
         GrTexture* fTexture = nullptr;
-        uint32_t fTextureContextID = SK_InvalidUniqueID;
+        GrDirectContext::DirectContextID fTextureContextID;
         bool fFulfillProcFailed = false;
     } callback(fulfillProc, std::move(releaseHelper));
 
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 7e8fc84..c4d2168 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -1561,15 +1561,15 @@
     REPORTER_ASSERT(reporter, 0 == (freed[0] + freed[1] + freed[2]));
 
     // Send message to free the first resource
-    GrTextureFreedMessage msg1{wrapped[0], dContext->priv().contextID()};
-    SkMessageBus<GrTextureFreedMessage, uint32_t>::Post(msg1);
+    GrTextureFreedMessage msg1{wrapped[0], dContext->directContextID()};
+    SkMessageBus<GrTextureFreedMessage, GrDirectContext::DirectContextID>::Post(msg1);
     cache->purgeAsNeeded();
 
     REPORTER_ASSERT(reporter, 1 == (freed[0] + freed[1] + freed[2]));
     REPORTER_ASSERT(reporter, 1 == freed[0]);
 
-    GrTextureFreedMessage msg2{wrapped[2], dContext->priv().contextID()};
-    SkMessageBus<GrTextureFreedMessage, uint32_t>::Post(msg2);
+    GrTextureFreedMessage msg2{wrapped[2], dContext->directContextID()};
+    SkMessageBus<GrTextureFreedMessage, GrDirectContext::DirectContextID>::Post(msg2);
     cache->purgeAsNeeded();
 
     REPORTER_ASSERT(reporter, 2 == (freed[0] + freed[1] + freed[2]));
@@ -1606,13 +1606,13 @@
 // This simulates a portion of Chrome's context abandonment processing.
 // Please see: crbug.com/1011368 and crbug.com/1014993
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceMessagesAfterAbandon, reporter, ctxInfo) {
-    auto context = ctxInfo.directContext();
-    GrGpu* gpu = context->priv().getGpu();
-    GrResourceCache* cache = context->priv().getResourceCache();
+    auto dContext = ctxInfo.directContext();
+    GrGpu* gpu = dContext->priv().getGpu();
+    GrResourceCache* cache = dContext->priv().getResourceCache();
 
-    GrBackendTexture backend = context->createBackendTexture(16, 16,
-                                                             SkColorType::kRGBA_8888_SkColorType,
-                                                             GrMipmapped::kNo, GrRenderable::kNo);
+    GrBackendTexture backend = dContext->createBackendTexture(16, 16,
+                                                              SkColorType::kRGBA_8888_SkColorType,
+                                                              GrMipmapped::kNo, GrRenderable::kNo);
     GrTexture* tex = gpu->wrapBackendTexture(backend,
                                              GrWrapOwnership::kBorrow_GrWrapOwnership,
                                              GrWrapCacheable::kYes,
@@ -1637,18 +1637,18 @@
 
     // We must delete the backend texture before abandoning the context in vulkan. We just do it
     // for all the backends for consistency.
-    context->deleteBackendTexture(backend);
-    context->abandonContext();
+    dContext->deleteBackendTexture(backend);
+    dContext->abandonContext();
 
     REPORTER_ASSERT(reporter, 1 == freed);
 
     // In the past, creating this message could cause an exception due to
     // an un-safe downcast from GrTexture to GrGpuResource
-    GrTextureFreedMessage msg{tex, context->priv().contextID()};
-    SkMessageBus<GrTextureFreedMessage, uint32_t>::Post(msg);
+    GrTextureFreedMessage msg{tex, dContext->directContextID()};
+    SkMessageBus<GrTextureFreedMessage, GrDirectContext::DirectContextID>::Post(msg);
 
     // This doesn't actually do anything but it does trigger us to read messages
-    context->purgeUnlockedResources(false);
+    dContext->purgeUnlockedResources(false);
 }
 
 ////////////////////////////////////////////////////////////////////////////////