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 #include "tools/gpu/ManagedBackendTexture.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkImageInfo.h"
12 #include "src/core/SkMipmap.h"
13 #include "src/gpu/RefCntedCallback.h"
14 #ifdef SK_GANESH
15 #include "include/private/gpu/ganesh/GrTypesPriv.h"
16 #endif
17 #ifdef SK_GRAPHITE
18 #include "include/gpu/graphite/Recorder.h"
19 #include "src/gpu/graphite/Caps.h"
20 #endif
21
22 using Mipmapped = skgpu::Mipmapped;
23 using Protected = skgpu::Protected;
24 using Renderable = skgpu::Renderable;
25
26 #ifdef SK_GANESH
27 namespace {
28
29 struct Context {
30 GrGpuFinishedProc fWrappedProc = nullptr;
31 GrGpuFinishedContext fWrappedContext = nullptr;
32 sk_sp<sk_gpu_test::ManagedBackendTexture> fMBETs[SkYUVAInfo::kMaxPlanes];
33 };
34
35 } // anonymous namespace
36
37 namespace sk_gpu_test {
38
ReleaseProc(void * ctx)39 void ManagedBackendTexture::ReleaseProc(void* ctx) {
40 std::unique_ptr<Context> context(static_cast<Context*>(ctx));
41 if (context->fWrappedProc) {
42 context->fWrappedProc(context->fWrappedContext);
43 }
44 }
45
~ManagedBackendTexture()46 ManagedBackendTexture::~ManagedBackendTexture() {
47 if (fDContext && fTexture.isValid()) {
48 fDContext->deleteBackendTexture(fTexture);
49 }
50 }
51
releaseContext(GrGpuFinishedProc wrappedProc,GrGpuFinishedContext wrappedCtx) const52 void* ManagedBackendTexture::releaseContext(GrGpuFinishedProc wrappedProc,
53 GrGpuFinishedContext wrappedCtx) const {
54 // Make sure we don't get a wrapped ctx without a wrapped proc
55 SkASSERT(!wrappedCtx || wrappedProc);
56 return new Context{wrappedProc, wrappedCtx, {sk_ref_sp(this)}};
57 }
58
MakeYUVAReleaseContext(const sk_sp<ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes])59 void* ManagedBackendTexture::MakeYUVAReleaseContext(
60 const sk_sp<ManagedBackendTexture> mbets[SkYUVAInfo::kMaxPlanes]) {
61 auto context = new Context;
62 for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) {
63 context->fMBETs[i] = mbets[i];
64 }
65 return context;
66 }
67
refCountedCallback() const68 sk_sp<skgpu::RefCntedCallback> ManagedBackendTexture::refCountedCallback() const {
69 return skgpu::RefCntedCallback::Make(ReleaseProc, this->releaseContext());
70 }
71
wasAdopted()72 void ManagedBackendTexture::wasAdopted() { fTexture = {}; }
73
MakeFromInfo(GrDirectContext * dContext,const SkImageInfo & ii,Mipmapped mipmapped,Renderable renderable,Protected isProtected)74 sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromInfo(GrDirectContext* dContext,
75 const SkImageInfo& ii,
76 Mipmapped mipmapped,
77 Renderable renderable,
78 Protected isProtected) {
79 return MakeWithoutData(dContext,
80 ii.width(),
81 ii.height(),
82 ii.colorType(),
83 mipmapped,
84 renderable,
85 isProtected);
86 }
87
MakeFromBitmap(GrDirectContext * dContext,const SkBitmap & src,Mipmapped mipmapped,Renderable renderable,Protected isProtected)88 sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromBitmap(GrDirectContext* dContext,
89 const SkBitmap& src,
90 Mipmapped mipmapped,
91 Renderable renderable,
92 Protected isProtected) {
93 SkPixmap srcPixmap;
94 if (!src.peekPixels(&srcPixmap)) {
95 return nullptr;
96 }
97
98 return MakeFromPixmap(dContext, srcPixmap, mipmapped, renderable, isProtected);
99 }
100
MakeFromPixmap(GrDirectContext * dContext,const SkPixmap & src,Mipmapped mipmapped,Renderable renderable,Protected isProtected)101 sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromPixmap(GrDirectContext* dContext,
102 const SkPixmap& src,
103 Mipmapped mipmapped,
104 Renderable renderable,
105 Protected isProtected) {
106 std::vector<SkPixmap> levels({src});
107 std::unique_ptr<SkMipmap> mm;
108
109 if (mipmapped == Mipmapped::kYes) {
110 mm.reset(SkMipmap::Build(src, nullptr));
111 if (!mm) {
112 return nullptr;
113 }
114 for (int i = 0; i < mm->countLevels(); ++i) {
115 SkMipmap::Level level;
116 SkAssertResult(mm->getLevel(i, &level));
117 levels.push_back(level.fPixmap);
118 }
119 }
120 return MakeWithData(dContext,
121 levels.data(),
122 static_cast<int>(levels.size()),
123 kTopLeft_GrSurfaceOrigin,
124 renderable,
125 isProtected);
126 }
127
128 } // namespace sk_gpu_test
129
130 #endif // SK_GANESH
131
132 #ifdef SK_GRAPHITE
133 using Recorder = skgpu::graphite::Recorder;
134
135 namespace {
136
137 struct MBETContext {
MBETContext__anon71a6d1300211::MBETContext138 MBETContext(const sk_sp<sk_gpu_test::ManagedGraphiteTexture>& tex)
139 : fMBETs{tex, nullptr, nullptr, nullptr} {}
MBETContext__anon71a6d1300211::MBETContext140 MBETContext(const sk_sp<sk_gpu_test::ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes])
141 : fMBETs{mbets[0], mbets[1], mbets[2], mbets[3]} {}
142 sk_sp<sk_gpu_test::ManagedGraphiteTexture> fMBETs[SkYUVAInfo::kMaxPlanes];
143 };
144
145 } // anonymous namespace
146
147 namespace sk_gpu_test {
148
ReleaseProc(void * ctx)149 void ManagedGraphiteTexture::ReleaseProc(void* ctx) {
150 std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
151 }
152
FinishedProc(void * ctx,skgpu::CallbackResult)153 void ManagedGraphiteTexture::FinishedProc(void* ctx, skgpu::CallbackResult) {
154 std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
155 }
ImageReleaseProc(void * ctx)156 void ManagedGraphiteTexture::ImageReleaseProc(void* ctx) {
157 std::unique_ptr<MBETContext> context(static_cast<MBETContext*>(ctx));
158 }
159
~ManagedGraphiteTexture()160 ManagedGraphiteTexture::~ManagedGraphiteTexture() {
161 if (fContext && fTexture.isValid()) {
162 fContext->deleteBackendTexture(fTexture);
163 }
164 }
165
releaseContext() const166 void* ManagedGraphiteTexture::releaseContext() const {
167 return new MBETContext{{sk_ref_sp(this)}};
168 }
169
MakeYUVAReleaseContext(const sk_sp<ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes])170 void* ManagedGraphiteTexture::MakeYUVAReleaseContext(
171 const sk_sp<ManagedGraphiteTexture> mbets[SkYUVAInfo::kMaxPlanes]) {
172 return new MBETContext(mbets);
173 }
174
refCountedCallback() const175 sk_sp<skgpu::RefCntedCallback> ManagedGraphiteTexture::refCountedCallback() const {
176 return skgpu::RefCntedCallback::Make(FinishedProc, this->releaseContext());
177 }
178
MakeUnInit(Recorder * recorder,const SkImageInfo & ii,Mipmapped mipmapped,Renderable renderable,Protected isProtected)179 sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeUnInit(Recorder* recorder,
180 const SkImageInfo& ii,
181 Mipmapped mipmapped,
182 Renderable renderable,
183 Protected isProtected) {
184 sk_sp<ManagedGraphiteTexture> mbet(new ManagedGraphiteTexture);
185 mbet->fContext = recorder->priv().context();
186 const skgpu::graphite::Caps* caps = recorder->priv().caps();
187
188 skgpu::graphite::TextureInfo info = caps->getDefaultSampledTextureInfo(ii.colorType(),
189 mipmapped,
190 isProtected,
191 renderable);
192
193 mbet->fTexture = recorder->createBackendTexture(ii.dimensions(), info);
194 if (!mbet->fTexture.isValid()) {
195 return nullptr;
196 }
197
198 recorder->addFinishInfo({mbet->releaseContext(), FinishedProc});
199
200 return mbet;
201 }
202
MakeFromPixmap(Recorder * recorder,const SkPixmap & src,Mipmapped mipmapped,Renderable renderable,Protected isProtected)203 sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeFromPixmap(Recorder* recorder,
204 const SkPixmap& src,
205 Mipmapped mipmapped,
206 Renderable renderable,
207 Protected isProtected) {
208 sk_sp<ManagedGraphiteTexture> mbet = MakeUnInit(recorder, src.info(), mipmapped, renderable,
209 isProtected);
210 if (!mbet) {
211 return nullptr;
212 }
213
214 std::vector<SkPixmap> levels({src});
215 std::unique_ptr<SkMipmap> mm;
216
217 if (mipmapped == Mipmapped::kYes) {
218 mm.reset(SkMipmap::Build(src, nullptr));
219 if (!mm) {
220 return nullptr;
221 }
222 for (int i = 0; i < mm->countLevels(); ++i) {
223 SkMipmap::Level level;
224 SkAssertResult(mm->getLevel(i, &level));
225 levels.push_back(level.fPixmap);
226 }
227 }
228
229 if (!recorder->updateBackendTexture(mbet->fTexture,
230 levels.data(),
231 static_cast<int>(levels.size()))) {
232 return nullptr;
233 }
234
235 return mbet;
236 }
237
MakeMipmappedFromPixmaps(Recorder * recorder,SkSpan<const SkPixmap> levels,skgpu::Renderable renderable,skgpu::Protected isProtected)238 sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeMipmappedFromPixmaps(
239 Recorder* recorder,
240 SkSpan<const SkPixmap> levels,
241 skgpu::Renderable renderable,
242 skgpu::Protected isProtected) {
243 if (levels.empty()) {
244 return nullptr;
245 }
246 sk_sp<ManagedGraphiteTexture> mbet = MakeUnInit(recorder,
247 levels[0].info(),
248 Mipmapped::kYes,
249 renderable,
250 isProtected);
251 if (!recorder->updateBackendTexture(mbet->fTexture,
252 levels.data(),
253 static_cast<int>(levels.size()))) {
254 return nullptr;
255 }
256
257 return mbet;
258 }
259
MakeFromCompressedData(Recorder * recorder,SkISize dimensions,SkTextureCompressionType compression,sk_sp<SkData> src,skgpu::Mipmapped mipmapped,skgpu::Protected isProtected)260 sk_sp<ManagedGraphiteTexture> ManagedGraphiteTexture::MakeFromCompressedData(
261 Recorder* recorder,
262 SkISize dimensions,
263 SkTextureCompressionType compression,
264 sk_sp<SkData> src,
265 skgpu::Mipmapped mipmapped,
266 skgpu::Protected isProtected) {
267 sk_sp<ManagedGraphiteTexture> mbet(new ManagedGraphiteTexture);
268 mbet->fContext = recorder->priv().context();
269 const skgpu::graphite::Caps* caps = recorder->priv().caps();
270
271 skgpu::graphite::TextureInfo info = caps->getDefaultCompressedTextureInfo(compression,
272 mipmapped,
273 isProtected);
274
275 mbet->fTexture = recorder->createBackendTexture(dimensions, info);
276 if (!mbet->fTexture.isValid()) {
277 return nullptr;
278 }
279
280 recorder->addFinishInfo({mbet->releaseContext(), FinishedProc});
281
282 if (!recorder->updateCompressedBackendTexture(mbet->fTexture,
283 src->data(),
284 src->size())) {
285 return nullptr;
286 }
287
288 return mbet;
289 }
290
291 } // namespace sk_gpu_test
292
293 #endif // SK_GRAPHITE
294