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 // NOTE: We would like to validate that the owning context hasn't been abandoned, but we can't
40 // do that safely (we might be on another thread). So assume everything is fine.
41 bool onIsValid(GrContext*) const override { return true; }
42
43 GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&, const SkIPoint&,
44 GrMipMapped mipMapped, GrImageTexGenPolicy) override;
45
46private:
47 GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin,
48 uint32_t owningContextID, std::unique_ptr<GrSemaphore>,
49 const GrBackendTexture&);
50
51 static void ReleaseRefHelper_TextureReleaseProc(void* ctx);
52
53 class RefHelper : public SkNVRefCnt<RefHelper> {
54 public:
55 RefHelper(GrTexture*, uint32_t owningContextID, std::unique_ptr<GrSemaphore>);
56
57 ~RefHelper();
58
59 GrTexture* fOriginalTexture;
60 uint32_t fOwningContextID;
61
62 // We use this key so that we don't rewrap the GrBackendTexture in a GrTexture for each
63 // proxy created from this generator for a particular borrowing context.
64 GrUniqueKey fBorrowedTextureKey;
65 // There is no ref associated with this pointer. We rely on our atomic bookkeeping with the
66 // context ID to know when this pointer is valid and safe to use. This is used to make sure
67 // all uses of the wrapped texture are finished on the borrowing context before we open
68 // this back up to other contexts. In general a ref to this release proc is owned by all
69 // proxies and gpu uses of the backend texture.
70 GrRefCntedCallback* fBorrowingContextReleaseProc;
71 uint32_t fBorrowingContextID;
72
73 std::unique_ptr<GrSemaphore> fSemaphore;
74 };
75
76 RefHelper* fRefHelper;
77 // This Mutex is used to guard the borrowing of the texture to one GrContext at a time as well
78 // as the creation of the fBorrowingContextReleaseProc. The latter happening if two threads with
79 // the same consuming GrContext try to generate a texture at the same time.
80 SkMutex fBorrowingMutex;
81
82 GrBackendTexture fBackendTexture;
83 GrSurfaceOrigin fSurfaceOrigin;
84
85 typedef SkImageGenerator INHERITED;
86};
87#endif // GrBackendTextureImageGenerator_DEFINED
88