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