1 /*
2  * Copyright 2020 Google LLC
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 
8 #ifndef ManagedBackendTexture_DEFINED
9 #define ManagedBackendTexture_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkYUVAInfo.h"
13 #include "include/gpu/GrDirectContext.h"
14 
15 class GrRefCntedCallback;
16 struct SkImageInfo;
17 
18 namespace sk_gpu_test {
19 
20 class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
21 public:
22     /**
23      * Make a managed backend texture with initial pixmap/color data. The 'Args' are any valid set
24      * of arguments to GrDirectContext::createBackendTexture that takes data but with the release
25      * proc/context omitted as the ManagedBackendTexture will provide them.
26      */
27     template <typename... Args>
28     static sk_sp<ManagedBackendTexture> MakeWithData(GrDirectContext*, Args&&...);
29 
30     /**
31      * Make a managed backend texture without initial data. The 'Args' are any valid set of
32      * arguments to GrDirectContext::createBackendTexture that does not take data. Because our
33      * createBackendTexture methods that *do* take data also use default args for the proc/context
34      * this can be used to make a texture with data but then the MBET won't be able to ensure that
35      * the upload has completed before the texture is deleted. Use the WithData variant instead to
36      * avoid this issue.
37      */
38     template <typename... Args>
39     static sk_sp<ManagedBackendTexture> MakeWithoutData(GrDirectContext*, Args&&...);
40 
41 
42     static sk_sp<ManagedBackendTexture> MakeFromInfo(GrDirectContext* dContext,
43                                                      const SkImageInfo&,
44                                                      GrMipmapped = GrMipmapped::kNo,
45                                                      GrRenderable = GrRenderable::kNo,
46                                                      GrProtected = GrProtected::kNo);
47 
48     static sk_sp<ManagedBackendTexture> MakeFromBitmap(GrDirectContext*,
49                                                        const SkBitmap&,
50                                                        GrMipmapped,
51                                                        GrRenderable,
52                                                        GrProtected = GrProtected::kNo);
53 
54     static sk_sp<ManagedBackendTexture> MakeFromPixmap(GrDirectContext*,
55                                                        const SkPixmap&,
56                                                        GrMipmapped,
57                                                        GrRenderable,
58                                                        GrProtected = GrProtected::kNo);
59 
60     /** GrGpuFinishedProc or image/surface release proc. */
61     static void ReleaseProc(void* context);
62 
63     ~ManagedBackendTexture();
64 
65     /**
66      * The context to use with ReleaseProc. This adds a ref so it *must* be balanced by a call to
67      * ReleaseProc. If a wrappedProc is provided then it will be called by ReleaseProc.
68      */
69     void* releaseContext(GrGpuFinishedProc wrappedProc = nullptr,
70                          GrGpuFinishedContext wrappedContext = nullptr) const;
71 
72     sk_sp<GrRefCntedCallback> refCountedCallback() const;
73 
74     /**
75      * Call if the underlying GrBackendTexture was adopted by a GrContext. This clears this out the
76      * MBET without deleting the texture.
77      */
78     void wasAdopted();
79 
80     /**
81      * SkImage::MakeFromYUVATextures takes a single release proc that is called once for all the
82      * textures. This makes a single release context for the group of textures. It's used with the
83      * standard ReleaseProc. Like releaseContext(), it must be balanced by a ReleaseProc call for
84      * proper ref counting.
85      */
86     static void* MakeYUVAReleaseContext(const sk_sp<ManagedBackendTexture>[SkYUVAInfo::kMaxPlanes]);
87 
texture()88     const GrBackendTexture& texture() { return fTexture; }
89 
90 private:
91     ManagedBackendTexture() = default;
92     ManagedBackendTexture(const ManagedBackendTexture&) = delete;
93     ManagedBackendTexture(ManagedBackendTexture&&) = delete;
94 
95     sk_sp<GrDirectContext> fDContext;
96     GrBackendTexture fTexture;
97 };
98 
99 template <typename... Args>
MakeWithData(GrDirectContext * dContext,Args &&...args)100 inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithData(GrDirectContext* dContext,
101                                                                         Args&&... args) {
102     sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
103     mbet->fDContext = sk_ref_sp(dContext);
104     mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...,
105                                                     ReleaseProc,
106                                                     mbet->releaseContext());
107     if (!mbet->fTexture.isValid()) {
108         return nullptr;
109     }
110     return mbet;
111 }
112 
113 template <typename... Args>
MakeWithoutData(GrDirectContext * dContext,Args &&...args)114 inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithoutData(
115         GrDirectContext* dContext,
116         Args&&... args) {
117     GrBackendTexture texture =
118             dContext->createBackendTexture(std::forward<Args>(args)...);
119     if (!texture.isValid()) {
120         return nullptr;
121     }
122     sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
123     mbet->fDContext = sk_ref_sp(dContext);
124     mbet->fTexture = std::move(texture);
125     return mbet;
126 }
127 
128 }  // namespace sk_gpu_test
129 
130 #endif
131