Home | History | Annotate | Download | only in gpu
      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.
     40     bool onIsValid(GrContext*) const override { return true; }
     41 
     42 #if SK_SUPPORT_GPU
     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:
     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