1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #ifndef GrBackendTextureImageGenerator_DEFINED 8 #define GrBackendTextureImageGenerator_DEFINED 9 10 #include "include/core/SkImageGenerator.h" 11 #include "include/gpu/GrBackendSurface.h" 12 #include "include/gpu/GrDirectContext.h" 13 #include "include/private/base/SkMutex.h" 14 #include "src/gpu/ResourceKey.h" 15 #include "src/gpu/ganesh/GrTexture.h" 16 17 class GrSemaphore; 18 19 /* 20 * This ImageGenerator is used to wrap a texture in one GrContext and can then be used as a source 21 * in another GrContext. It holds onto a semaphore which the producing GrContext will signal and the 22 * consuming GrContext will wait on before using the texture. Only one GrContext can ever be used 23 * as a consumer (this is mostly because Vulkan can't allow multiple things to wait on the same 24 * semaphore). 25 * 26 * In practice, this capability is used by clients to create backend-specific texture resources in 27 * one thread (with, say, GrContext-A) and then ship them over to another GrContext (say, 28 * GrContext-B) which will then use the texture as a source for draws. GrContext-A uses the 29 * semaphore to notify GrContext-B when the shared texture is ready to use. 30 */ 31 class GrBackendTextureImageGenerator : public SkImageGenerator { 32 public: 33 static std::unique_ptr<SkImageGenerator> Make(sk_sp<GrTexture>, GrSurfaceOrigin, 34 std::unique_ptr<GrSemaphore>, SkColorType, 35 SkAlphaType, sk_sp<SkColorSpace>); 36 37 ~GrBackendTextureImageGenerator() override; 38 39 protected: onIsValid(GrRecordingContext * context)40 bool onIsValid(GrRecordingContext* context) const override { 41 if (context && context->abandoned()) { 42 return false; 43 } 44 return true; 45 } 46 47 GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, 48 GrMipmapped mipmapped, GrImageTexGenPolicy) override; 49 50 private: 51 GrBackendTextureImageGenerator(const SkColorInfo&, 52 sk_sp<GrTexture>, 53 GrSurfaceOrigin, 54 GrDirectContext::DirectContextID owningContextID, 55 std::unique_ptr<GrSemaphore>); 56 57 static void ReleaseRefHelper_TextureReleaseProc(void* ctx); 58 59 class RefHelper : public SkNVRefCnt<RefHelper> { 60 public: 61 RefHelper(sk_sp<GrTexture>, 62 GrDirectContext::DirectContextID owningContextID, 63 std::unique_ptr<GrSemaphore>); 64 65 ~RefHelper(); 66 67 sk_sp<GrTexture> fOriginalTexture; 68 GrDirectContext::DirectContextID fOwningContextID; 69 70 // We use this key so that we don't rewrap the GrBackendTexture in a GrTexture for each 71 // proxy created from this generator for a particular borrowing context. 72 skgpu::UniqueKey fBorrowedTextureKey; 73 // There is no ref associated with this pointer. We rely on our atomic bookkeeping with the 74 // context ID to know when this pointer is valid and safe to use. This is used to make sure 75 // all uses of the wrapped texture are finished on the borrowing context before we open 76 // this back up to other contexts. In general a ref to this release proc is owned by all 77 // proxies and gpu uses of the backend texture. 78 skgpu::RefCntedCallback* fBorrowingContextReleaseProc; 79 GrDirectContext::DirectContextID fBorrowingContextID; 80 81 std::unique_ptr<GrSemaphore> fSemaphore; 82 }; 83 84 RefHelper* fRefHelper; 85 // This Mutex is used to guard the borrowing of the texture to one GrContext at a time as well 86 // as the creation of the fBorrowingContextReleaseProc. The latter happening if two threads with 87 // the same consuming GrContext try to generate a texture at the same time. 88 SkMutex fBorrowingMutex; 89 90 GrBackendTexture fBackendTexture; 91 GrSurfaceOrigin fSurfaceOrigin; 92 93 using INHERITED = SkImageGenerator; 94 }; 95 #endif // GrBackendTextureImageGenerator_DEFINED 96