Add GrExternalTextureData and SkCrossContextImageData

GrExternalTextureData is an API for exporting the backend-specific
information about a texture in a type-safe way, and without pointing
into the GrTexture. The new detachBackendTexture API lets us release
ownership of a texture to the client.

SkCrossContextImageData is the public API that lets clients upload
textures on one thread/GrContext, then safely transfer ownership to
another thread and GrContext for rendering.

Only GL is implemented/supported right now. Vulkan support requires
that we add thread-safe memory pools, or otherwise transfer the
actual memory block containing the texture to the new context.

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

BUG=skia:

Change-Id: I48ebd57d1ea0cfd3a1db10c475f2903afb821966
Reviewed-on: https://skia-review.googlesource.com/8960
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index ddf2252..0bcb7e8 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -603,6 +603,15 @@
         fFenceSyncSupport = true;
     }
 
+    // Safely moving textures between contexts requires fences. The Windows Intel driver has a
+    // bug with deleting and reusing texture IDs across contexts, so disallow this feature.
+    fCrossContextTextureSupport = fFenceSyncSupport;
+#ifdef SK_BUILD_FOR_WIN
+    if (kIntel_GrGLVendor == ctxInfo.vendor()) {
+        fCrossContextTextureSupport = false;
+    }
+#endif
+
     // We support manual mip-map generation (via iterative downsampling draw calls). This fixes
     // bugs on some cards/drivers that produce incorrect mip-maps for sRGB textures when using
     // glGenerateMipmap. Our implementation requires mip-level sampling control. Additionally,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ad00b0a..5dce7d1 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4741,3 +4741,7 @@
 void GrGLGpu::deleteFence(GrFence fence) const {
     GL_CALL(DeleteSync((GrGLsync)fence));
 }
+
+void GrGLGpu::flush() {
+    GL_CALL(Flush());
+}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index fdc2ebb..b6ca4f6 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -150,6 +150,8 @@
     bool waitFence(GrFence, uint64_t timeout) const override;
     void deleteFence(GrFence) const override;
 
+    void flush() override;
+
 private:
     GrGLGpu(GrGLContext* ctx, GrContext* context);
 
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index edce7b1..a560988 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -5,9 +5,11 @@
  * found in the LICENSE file.
  */
 
+#include "GrContext.h"
 #include "GrGLTexture.h"
 #include "GrGLGpu.h"
 #include "GrShaderCaps.h"
+#include "SkMakeUnique.h"
 #include "SkTraceMemoryDump.h"
 
 #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
@@ -111,6 +113,23 @@
     return reinterpret_cast<GrBackendObject>(&fInfo);
 }
 
+std::unique_ptr<GrExternalTextureData> GrGLTexture::detachBackendTexture() {
+    // Flush any pending writes to this texture, as well GL itself
+    GrFence fence = this->getContext()->prepareSurfaceForExternalIOAndFlush(this);
+
+    // Make a copy of our GL-specific information
+    auto data = skstd::make_unique<GrGLExternalTextureData>(fInfo, fence);
+
+    // Ensure the cache can't reach this texture anymore
+    this->detachFromCache();
+
+    // Detach from the GL object, so we don't use it (or try to delete it when we're freed)
+    fInfo.fTarget = 0;
+    fInfo.fID = 0;
+
+    return std::move(data);
+}
+
 void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
                                    const SkString& dumpName) const {
     SkString texture_id;
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 029fd87..16b47f1 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -71,6 +71,7 @@
     void onRelease() override;
     void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
                           const SkString& dumpName) const override;
+    std::unique_ptr<GrExternalTextureData> detachBackendTexture() override;
 
 private:
     TexParams                       fTexParams;