xref: /aosp_15_r20/external/skia/tools/gpu/ManagedBackendTexture.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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