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>, SkColorType, 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 onCanGenerateTexture()42 TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; } 43 sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&, 44 bool willNeedMipMaps) override; 45 46 private: 47 GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin, 48 uint32_t owningContextID, sk_sp<GrSemaphore>, 49 const GrBackendTexture&); 50 51 static void ReleaseRefHelper_TextureReleaseProc(void* ctx); 52 53 class RefHelper : public SkNVRefCnt<RefHelper> { 54 public: RefHelper(GrTexture * texture,uint32_t owningContextID)55 RefHelper(GrTexture* texture, uint32_t owningContextID) 56 : fOriginalTexture(texture) 57 , fOwningContextID(owningContextID) 58 , fBorrowedTexture(nullptr) 59 , fBorrowingContextReleaseProc(nullptr) 60 , fBorrowingContextID(SK_InvalidGenID) {} 61 62 ~RefHelper(); 63 64 GrTexture* fOriginalTexture; 65 uint32_t fOwningContextID; 66 67 // There is never a ref associated with this pointer. We rely on our atomic bookkeeping 68 // with the context ID to know when this pointer is valid and safe to use. This lets us 69 // avoid releasing a ref from another thread, or get into races during context shutdown. 70 GrTexture* fBorrowedTexture; 71 // For the same reason as the fBorrowedTexture, there is no ref associated with this 72 // pointer. The fBorrowingContextReleaseProc is used to make sure all uses of the wrapped 73 // texture are finished on the borrowing context before we open this back up to other 74 // contexts. In general a ref to this release proc is owned by all proxies and gpu uses of 75 // the backend texture. 76 GrReleaseProcHelper* fBorrowingContextReleaseProc; 77 uint32_t fBorrowingContextID; 78 }; 79 80 RefHelper* fRefHelper; 81 // This Mutex is used to guard the borrowing of the texture to one GrContext at a time as well 82 // as the creation of the fBorrowingContextReleaseProc. The latter happening if two threads with 83 // the same consuming GrContext try to generate a texture at the same time. 84 SkMutex fBorrowingMutex; 85 86 sk_sp<GrSemaphore> fSemaphore; 87 88 GrBackendTexture fBackendTexture; 89 GrPixelConfig fConfig; 90 GrSurfaceOrigin fSurfaceOrigin; 91 92 typedef SkImageGenerator INHERITED; 93 }; 94 #endif // GrBackendTextureImageGenerator_DEFINED 95