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;