Added SkImage::MakeCrossContextFromEncoded

Designed for Flutter's threading architecture, with
an eye to being useful to other clients. Under the
hood, uses a new image generator class to lazily wrap
a texture for multiple GrContexts.

Re-land of https://skia-review.googlesource.com/c/14180/

Bug: skia:
Change-Id: I3dd382640629b79b3058f18fee68d043566e43e5
Reviewed-on: https://skia-review.googlesource.com/15895
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index e3373b2..299f63f 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -18,6 +18,8 @@
 
 DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage);
 
+DECLARE_SKMESSAGEBUS_MESSAGE(GrGpuResourceFreedMessage);
+
 //////////////////////////////////////////////////////////////////////////////
 
 GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() {
@@ -59,7 +61,7 @@
  //////////////////////////////////////////////////////////////////////////////
 
 
-GrResourceCache::GrResourceCache(const GrCaps* caps)
+GrResourceCache::GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID)
     : fTimestamp(0)
     , fMaxCount(kDefaultMaxCount)
     , fMaxBytes(kDefaultMaxSize)
@@ -75,6 +77,7 @@
     , fBudgetedBytes(0)
     , fRequestFlush(false)
     , fExternalFlushCnt(0)
+    , fContextUniqueID(contextUniqueID)
     , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) {
     SkDEBUGCODE(fCount = 0;)
     SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;)
@@ -186,6 +189,8 @@
 void GrResourceCache::releaseAll() {
     AutoValidate av(this);
 
+    this->processFreedGpuResources();
+
     while(fNonpurgeableResources.count()) {
         GrGpuResource* back = *(fNonpurgeableResources.end() - 1);
         SkASSERT(!back->wasDestroyed());
@@ -450,6 +455,8 @@
         this->processInvalidUniqueKeys(invalidKeyMsgs);
     }
 
+    this->processFreedGpuResources();
+
     if (fMaxUnusedFlushes > 0) {
         // We want to know how many complete flushes have occurred without the resource being used.
         // If the resource was tagged when fExternalFlushCnt was N then this means it became
@@ -534,6 +541,20 @@
     }
 }
 
+void GrResourceCache::insertCrossContextGpuResource(GrGpuResource* resource) {
+    resource->ref();
+}
+
+void GrResourceCache::processFreedGpuResources() {
+    SkTArray<GrGpuResourceFreedMessage> msgs;
+    fFreedGpuResourceInbox.poll(&msgs);
+    for (int i = 0; i < msgs.count(); ++i) {
+        if (msgs[i].fOwningUniqueID == fContextUniqueID) {
+            msgs[i].fResource->unref();
+        }
+    }
+}
+
 void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) {
     int index = fNonpurgeableResources.count();
     *fNonpurgeableResources.append() = resource;