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 #ifdef SK_GANESH
14 #include "include/gpu/ganesh/GrBackendSurface.h"
15 #include "include/gpu/ganesh/GrDirectContext.h"
16 #endif
17 #ifdef SK_GRAPHITE
18 #include "include/gpu/graphite/BackendTexture.h"
19 #include "include/gpu/graphite/Context.h"
20 #include "src/gpu/graphite/RecorderPriv.h"
21 #endif
22
23 namespace skgpu {
24 class RefCntedCallback;
25 }
26 namespace skgpu::graphite {
27 class Recorder;
28 }
29 class SkBitmap;
30 struct SkImageInfo;
31
32 #ifdef SK_GRAPHITE
33 using Recorder = skgpu::graphite::Recorder;
34 #endif
35
36 namespace sk_gpu_test {
37
38 #ifdef SK_GANESH
39 class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> {
40 public:
41 /**
42 * Make a managed backend texture with initial pixmap/color data. The 'Args' are any valid set
43 * of arguments to GrDirectContext::createBackendTexture that takes data but with the release
44 * proc/context omitted as the ManagedBackendTexture will provide them.
45 */
46 template <typename... Args>
47 static sk_sp<ManagedBackendTexture> MakeWithData(GrDirectContext*, Args&&...);
48
49 /**
50 * Make a managed backend texture without initial data. The 'Args' are any valid set of
51 * arguments to GrDirectContext::createBackendTexture that does not take data. Because our
52 * createBackendTexture methods that *do* take data also use default args for the proc/context
53 * this can be used to make a texture with data but then the MBET won't be able to ensure that
54 * the upload has completed before the texture is deleted. Use the WithData variant instead to
55 * avoid this issue.
56 */
57 template <typename... Args>
58 static sk_sp<ManagedBackendTexture> MakeWithoutData(GrDirectContext*, Args&&...);
59
60
61 static sk_sp<ManagedBackendTexture> MakeFromInfo(GrDirectContext* dContext,
62 const SkImageInfo&,
63 skgpu::Mipmapped = skgpu::Mipmapped::kNo,
64 skgpu::Renderable = skgpu::Renderable::kNo,
65 skgpu::Protected = skgpu::Protected::kNo);
66
67 static sk_sp<ManagedBackendTexture> MakeFromBitmap(GrDirectContext*,
68 const SkBitmap&,
69 skgpu::Mipmapped,
70 skgpu::Renderable,
71 skgpu::Protected = skgpu::Protected::kNo);
72
73 static sk_sp<ManagedBackendTexture> MakeFromPixmap(GrDirectContext*,
74 const SkPixmap&,
75 skgpu::Mipmapped,
76 skgpu::Renderable,
77 skgpu::Protected = skgpu::Protected::kNo);
78
79 /** GrGpuFinishedProc or image/surface release proc. */
80 static void ReleaseProc(void* context);
81
82 ~ManagedBackendTexture();
83
84 /**
85 * The context to use with ReleaseProc. This adds a ref so it *must* be balanced by a call to
86 * ReleaseProc. If a wrappedProc is provided then it will be called by ReleaseProc.
87 */
88 void* releaseContext(GrGpuFinishedProc wrappedProc = nullptr,
89 GrGpuFinishedContext wrappedContext = nullptr) const;
90
91 sk_sp<skgpu::RefCntedCallback> refCountedCallback() const;
92
93 /**
94 * Call if the underlying GrBackendTexture was adopted by a GrContext. This clears this out the
95 * MBET without deleting the texture.
96 */
97 void wasAdopted();
98
99 /**
100 * SkImages::TextureFromYUVATextures takes a single release proc that is called once for all the
101 * textures. This makes a single release context for the group of textures. It's used with the
102 * standard ReleaseProc. Like releaseContext(), it must be balanced by a ReleaseProc call for
103 * proper ref counting.
104 */
105 static void* MakeYUVAReleaseContext(const sk_sp<ManagedBackendTexture>[SkYUVAInfo::kMaxPlanes]);
106
texture()107 const GrBackendTexture& texture() { return fTexture; }
108
109 private:
110 ManagedBackendTexture() = default;
111 ManagedBackendTexture(const ManagedBackendTexture&) = delete;
112 ManagedBackendTexture(ManagedBackendTexture&&) = delete;
113
114 sk_sp<GrDirectContext> fDContext;
115 GrBackendTexture fTexture;
116 };
117
118 template <typename... Args>
MakeWithData(GrDirectContext * dContext,Args &&...args)119 inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithData(GrDirectContext* dContext,
120 Args&&... args) {
121 sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
122 mbet->fDContext = sk_ref_sp(dContext);
123 mbet->fTexture = dContext->createBackendTexture(std::forward<Args>(args)...,
124 ReleaseProc,
125 mbet->releaseContext());
126 if (!mbet->fTexture.isValid()) {
127 return nullptr;
128 }
129 return mbet;
130 }
131
132 template <typename... Args>
MakeWithoutData(GrDirectContext * dContext,Args &&...args)133 inline sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeWithoutData(
134 GrDirectContext* dContext,
135 Args&&... args) {
136 GrBackendTexture texture =
137 dContext->createBackendTexture(std::forward<Args>(args)...);
138 if (!texture.isValid()) {
139 return nullptr;
140 }
141 sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture);
142 mbet->fDContext = sk_ref_sp(dContext);
143 mbet->fTexture = std::move(texture);
144 return mbet;
145 }
146 #endif // SK_GANESH
147
148 #ifdef SK_GRAPHITE
149 /*
150 * Graphite version of ManagedBackendTexture
151 */
152 class ManagedGraphiteTexture : public SkNVRefCnt<ManagedGraphiteTexture> {
153 public:
154 static sk_sp<ManagedGraphiteTexture> MakeUnInit(Recorder*,
155 const SkImageInfo&,
156 skgpu::Mipmapped,
157 skgpu::Renderable,
158 skgpu::Protected = skgpu::Protected::kNo);
159
160 static sk_sp<ManagedGraphiteTexture> MakeFromPixmap(Recorder*,
161 const SkPixmap&,
162 skgpu::Mipmapped,
163 skgpu::Renderable,
164 skgpu::Protected = skgpu::Protected::kNo);
165
166 static sk_sp<ManagedGraphiteTexture> MakeMipmappedFromPixmaps(
167 Recorder*,
168 SkSpan<const SkPixmap> levels,
169 skgpu::Renderable,
170 skgpu::Protected = skgpu::Protected::kNo);
171
172 static sk_sp<ManagedGraphiteTexture> MakeFromCompressedData(
173 Recorder*,
174 SkISize dimmensions,
175 SkTextureCompressionType,
176 sk_sp<SkData>,
177 skgpu::Mipmapped,
178 skgpu::Protected = skgpu::Protected::kNo);
179
180 /** finished and image/surface release procs */
181 static void FinishedProc(void* context, skgpu::CallbackResult);
182 static void ReleaseProc(void* context);
183 static void ImageReleaseProc(void* context);
184
185 ~ManagedGraphiteTexture();
186
187 /**
188 * The context to use with the ReleaseProcs. This adds a ref so it *must* be balanced by a call
189 * to TextureReleaseProc or ImageReleaseProc.
190 */
191 void* releaseContext() const;
192
193 sk_sp<skgpu::RefCntedCallback> refCountedCallback() const;
194
195 /**
196 * SkImage::MakeGraphiteFromYUVABackendTextures takes a single release proc that is called once
197 * for all the textures. This makes a single release context for the group of textures. It's
198 * used with the standard ReleaseProc. Like releaseContext(), it must be balanced by a
199 * ReleaseProc call for proper ref counting.
200 */
201 static void* MakeYUVAReleaseContext(const sk_sp<ManagedGraphiteTexture>[SkYUVAInfo::kMaxPlanes]);
202
texture()203 const skgpu::graphite::BackendTexture& texture() { return fTexture; }
204
205 private:
206 ManagedGraphiteTexture() = default;
207 ManagedGraphiteTexture(const ManagedGraphiteTexture&) = delete;
208 ManagedGraphiteTexture(ManagedGraphiteTexture&&) = delete;
209
210 skgpu::graphite::Context* fContext;
211 skgpu::graphite::BackendTexture fTexture;
212 };
213
214 #endif // SK_GRAPHITE
215
216 } // namespace sk_gpu_test
217
218 #endif // ManagedBackendTexture_DEFINED
219