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 "SkImageGenerator.h" 11 12 #include "GrBackendSurface.h" 13 #include "SkMutex.h" 14 15 class GrSemaphore; 16 17 /* 18 * This ImageGenerator is used to wrap a texture in one GrContext and can then be used as a source 19 * in another GrContext. It holds onto a semaphore which the producing GrContext will signal and the 20 * consuming GrContext will wait on before using the texture. Only one GrContext can ever be used 21 * as a consumer (this is mostly because Vulkan can't allow multiple things to wait on the same 22 * semaphore). 23 * 24 * In practice, this capability is used by clients to create backend-specific texture resources in 25 * one thread (with, say, GrContext-A) and then ship them over to another GrContext (say, 26 * GrContext-B) which will then use the texture as a source for draws. GrContext-A uses the 27 * semaphore to notify GrContext-B when the shared texture is ready to use. 28 */ 29 class GrBackendTextureImageGenerator : public SkImageGenerator { 30 public: 31 static std::unique_ptr<SkImageGenerator> Make(sk_sp<GrTexture>, GrSurfaceOrigin, 32 sk_sp<GrSemaphore>, 33 SkAlphaType, sk_sp<SkColorSpace>); 34 35 ~GrBackendTextureImageGenerator() override; 36 37 protected: 38 // NOTE: We would like to validate that the owning context hasn't been abandoned, but we can't 39 // do that safely (we might be on another thread). So assume everything is fine. onIsValid(GrContext *)40 bool onIsValid(GrContext*) const override { return true; } 41 42 #if SK_SUPPORT_GPU onCanGenerateTexture()43 TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; } 44 sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&, 45 SkTransferFunctionBehavior, 46 bool willNeedMipMaps) override; 47 #endif 48 49 private: 50 GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin, 51 uint32_t owningContextID, sk_sp<GrSemaphore>, 52 const GrBackendTexture&); 53 54 static void ReleaseRefHelper_TextureReleaseProc(void* ctx); 55 56 class RefHelper : public SkNVRefCnt<RefHelper> { 57 public: RefHelper(GrTexture * texture,uint32_t owningContextID)58 RefHelper(GrTexture* texture, uint32_t owningContextID) 59 : fOriginalTexture(texture) 60 , fOwningContextID(owningContextID) 61 , fBorrowedTexture(nullptr) 62 , fBorrowingContextReleaseProc(nullptr) 63 , fBorrowingContextID(SK_InvalidGenID) {} 64 65 ~RefHelper(); 66 67 GrTexture* fOriginalTexture; 68 uint32_t fOwningContextID; 69 70 // There is never a ref associated with this pointer. We rely on our atomic bookkeeping 71 // with the context ID to know when this pointer is valid and safe to use. This lets us 72 // avoid releasing a ref from another thread, or get into races during context shutdown. 73 GrTexture* fBorrowedTexture; 74 // For the same reason as the fBorrowedTexture, there is no ref associated with this 75 // pointer. The fBorrowingContextReleaseProc is used to make sure all uses of the wrapped 76 // texture are finished on the borrowing context before we open this back up to other 77 // contexts. In general a ref to this release proc is owned by all proxies and gpu uses of 78 // the backend texture. 79 GrReleaseProcHelper* fBorrowingContextReleaseProc; 80 uint32_t fBorrowingContextID; 81 }; 82 83 RefHelper* fRefHelper; 84 // This Mutex is used to guard the borrowing of the texture to one GrContext at a time as well 85 // as the creation of the fBorrowingContextReleaseProc. The latter happening if two threads with 86 // the same consuming GrContext try to generate a texture at the same time. 87 SkMutex fBorrowingMutex; 88 89 sk_sp<GrSemaphore> fSemaphore; 90 91 GrBackendTexture fBackendTexture; 92 GrPixelConfig fConfig; 93 GrSurfaceOrigin fSurfaceOrigin; 94 95 typedef SkImageGenerator INHERITED; 96 }; 97 #endif // GrBackendTextureImageGenerator_DEFINED 98