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/GrResourceKey.h"
14#include "include/private/SkMutex.h"
15#include "src/gpu/GrTexture.h"
16
17class 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 */
31class GrBackendTextureImageGenerator : public SkImageGenerator {
32public:
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
39protected:
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&, const SkIPoint&,
48                                         GrMipmapped mipMapped, GrImageTexGenPolicy) override;
49
50private:
51    GrBackendTextureImageGenerator(const SkImageInfo& info,
52                                   GrTexture*,
53                                   GrSurfaceOrigin,
54                                   GrDirectContext::DirectContextID owningContextID,
55                                   std::unique_ptr<GrSemaphore>,
56                                   const GrBackendTexture&);
57
58    static void ReleaseRefHelper_TextureReleaseProc(void* ctx);
59
60    class RefHelper : public SkNVRefCnt<RefHelper> {
61    public:
62        RefHelper(GrTexture*,
63                  GrDirectContext::DirectContextID owningContextID,
64                  std::unique_ptr<GrSemaphore>);
65
66        ~RefHelper();
67
68        GrTexture*                       fOriginalTexture;
69        GrDirectContext::DirectContextID fOwningContextID;
70
71        // We use this key so that we don't rewrap the GrBackendTexture in a GrTexture for each
72        // proxy created from this generator for a particular borrowing context.
73        GrUniqueKey                      fBorrowedTextureKey;
74        // There is no ref associated with this pointer. We rely on our atomic bookkeeping with the
75        // context ID to know when this pointer is valid and safe to use. This is used to make sure
76        // all uses of the wrapped texture are finished on the borrowing context before we open
77        // this back up to other contexts. In general a ref to this release proc is owned by all
78        // proxies and gpu uses of the backend texture.
79        GrRefCntedCallback*              fBorrowingContextReleaseProc;
80        GrDirectContext::DirectContextID fBorrowingContextID;
81
82        std::unique_ptr<GrSemaphore>     fSemaphore;
83    };
84
85    RefHelper*       fRefHelper;
86    // This Mutex is used to guard the borrowing of the texture to one GrContext at a time as well
87    // as the creation of the fBorrowingContextReleaseProc. The latter happening if two threads with
88    // the same consuming GrContext try to generate a texture at the same time.
89    SkMutex          fBorrowingMutex;
90
91    GrBackendTexture fBackendTexture;
92    GrSurfaceOrigin  fSurfaceOrigin;
93
94    using INHERITED = SkImageGenerator;
95};
96#endif  // GrBackendTextureImageGenerator_DEFINED
97