/src/skia/tools/DDLPromiseImageHelper.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2018 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 | | |
8 | | #include "tools/DDLPromiseImageHelper.h" |
9 | | |
10 | | #include "include/core/SkPicture.h" |
11 | | #include "include/core/SkSerialProcs.h" |
12 | | #include "include/gpu/GrContextThreadSafeProxy.h" |
13 | | #include "include/gpu/GrDirectContext.h" |
14 | | #include "include/gpu/GrYUVABackendTextures.h" |
15 | | #include "include/gpu/ganesh/SkImageGanesh.h" |
16 | | #include "include/private/chromium/SkImageChromium.h" |
17 | | #include "src/codec/SkCodecImageGenerator.h" |
18 | | #include "src/core/SkCachedData.h" |
19 | | #include "src/core/SkMipmap.h" |
20 | | #include "src/core/SkTaskGroup.h" |
21 | | #include "src/gpu/ganesh/GrCaps.h" |
22 | | #include "src/gpu/ganesh/GrDirectContextPriv.h" |
23 | | #include "src/gpu/ganesh/image/SkImage_GaneshYUVA.h" |
24 | | #include "src/image/SkImage_Base.h" |
25 | | |
26 | | DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(int index, |
27 | | uint32_t originalUniqueID, |
28 | | const SkImageInfo& ii) |
29 | | : fIndex(index) |
30 | | , fOriginalUniqueID(originalUniqueID) |
31 | 0 | , fImageInfo(ii) { |
32 | 0 | } |
33 | | |
34 | | DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(PromiseImageInfo&& other) |
35 | | : fIndex(other.fIndex) |
36 | | , fOriginalUniqueID(other.fOriginalUniqueID) |
37 | | , fImageInfo(other.fImageInfo) |
38 | | , fBaseLevel(other.fBaseLevel) |
39 | | , fMipLevels(std::move(other.fMipLevels)) |
40 | 0 | , fYUVAPixmaps(std::move(other.fYUVAPixmaps)) { |
41 | 0 | for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) { |
42 | 0 | fCallbackContexts[i] = std::move(other.fCallbackContexts[i]); |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | 0 | DDLPromiseImageHelper::PromiseImageInfo::~PromiseImageInfo() {} |
47 | | |
48 | 0 | std::unique_ptr<SkPixmap[]> DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const { |
49 | 0 | SkASSERT(!this->isYUV()); |
50 | 0 | std::unique_ptr<SkPixmap[]> pixmaps(new SkPixmap[this->numMipLevels()]); |
51 | 0 | pixmaps[0] = fBaseLevel.pixmap(); |
52 | 0 | if (fMipLevels) { |
53 | 0 | for (int i = 0; i < fMipLevels->countLevels(); ++i) { |
54 | 0 | SkMipmap::Level mipLevel; |
55 | 0 | fMipLevels->getLevel(i, &mipLevel); |
56 | 0 | pixmaps[i+1] = mipLevel.fPixmap; |
57 | 0 | } |
58 | 0 | } |
59 | 0 | return pixmaps; |
60 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const Unexecuted instantiation: DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const |
61 | | |
62 | 0 | int DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const { |
63 | 0 | SkASSERT(!this->isYUV()); |
64 | 0 | return fMipLevels ? fMipLevels->countLevels()+1 : 1; |
65 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const Unexecuted instantiation: DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const |
66 | | |
67 | | void DDLPromiseImageHelper::PromiseImageInfo::setMipLevels(const SkBitmap& baseLevel, |
68 | 0 | std::unique_ptr<SkMipmap> mipLevels) { |
69 | 0 | fBaseLevel = baseLevel; |
70 | 0 | fMipLevels = std::move(mipLevels); |
71 | 0 | } |
72 | | |
73 | | /////////////////////////////////////////////////////////////////////////////////////////////////// |
74 | 0 | PromiseImageCallbackContext::~PromiseImageCallbackContext() { |
75 | 0 | SkASSERT(fDoneCnt == fNumImages); |
76 | 0 | SkASSERT(!fTotalFulfills || fDoneCnt); |
77 | |
|
78 | 0 | if (fPromiseImageTexture) { |
79 | 0 | fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture()); |
80 | 0 | } |
81 | 0 | } Unexecuted instantiation: PromiseImageCallbackContext::~PromiseImageCallbackContext() Unexecuted instantiation: PromiseImageCallbackContext::~PromiseImageCallbackContext() |
82 | | |
83 | 0 | void PromiseImageCallbackContext::setBackendTexture(const GrBackendTexture& backendTexture) { |
84 | 0 | SkASSERT(!fPromiseImageTexture); |
85 | 0 | SkASSERT(fBackendFormat == backendTexture.getBackendFormat()); |
86 | 0 | fPromiseImageTexture = GrPromiseImageTexture::Make(backendTexture); |
87 | 0 | } Unexecuted instantiation: PromiseImageCallbackContext::setBackendTexture(GrBackendTexture const&) Unexecuted instantiation: PromiseImageCallbackContext::setBackendTexture(GrBackendTexture const&) |
88 | | |
89 | 0 | void PromiseImageCallbackContext::destroyBackendTexture() { |
90 | 0 | SkASSERT(!fPromiseImageTexture || fPromiseImageTexture->unique()); |
91 | |
|
92 | 0 | if (fPromiseImageTexture) { |
93 | 0 | fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture()); |
94 | 0 | } |
95 | 0 | fPromiseImageTexture = nullptr; |
96 | 0 | } Unexecuted instantiation: PromiseImageCallbackContext::destroyBackendTexture() Unexecuted instantiation: PromiseImageCallbackContext::destroyBackendTexture() |
97 | | |
98 | | /////////////////////////////////////////////////////////////////////////////////////////////////// |
99 | | |
100 | | sk_sp<SkPicture> DDLPromiseImageHelper::recreateSKP(GrDirectContext* dContext, |
101 | 0 | SkPicture* inputPicture) { |
102 | 0 | SkSerialProcs procs; |
103 | |
|
104 | 0 | procs.fImageCtx = this; |
105 | 0 | procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> { |
106 | 0 | auto helper = static_cast<DDLPromiseImageHelper*>(ctx); |
107 | |
|
108 | 0 | int id = helper->findOrDefineImage(image); |
109 | | |
110 | | // Even if 'id' is invalid (i.e., -1) write it to the SKP |
111 | 0 | return SkData::MakeWithCopy(&id, sizeof(id)); |
112 | 0 | }; |
113 | |
|
114 | 0 | sk_sp<SkData> compressedPictureData = inputPicture->serialize(&procs); |
115 | 0 | if (!compressedPictureData) { |
116 | 0 | return nullptr; |
117 | 0 | } |
118 | | |
119 | 0 | this->createCallbackContexts(dContext); |
120 | |
|
121 | 0 | return this->reinflateSKP(dContext->threadSafeProxy(), compressedPictureData.get()); |
122 | 0 | } |
123 | | |
124 | | static GrBackendTexture create_yuva_texture(GrDirectContext* direct, |
125 | | const SkPixmap& pm, |
126 | 0 | int texIndex) { |
127 | 0 | SkASSERT(texIndex >= 0 && texIndex <= 3); |
128 | |
|
129 | 0 | bool finishedBECreate = false; |
130 | 0 | auto markFinished = [](void* context) { |
131 | 0 | *(bool*)context = true; |
132 | 0 | }; Unexecuted instantiation: DDLPromiseImageHelper.cpp:create_yuva_texture(GrDirectContext*, SkPixmap const&, int)::$_0::operator()(void*) const Unexecuted instantiation: DDLPromiseImageHelper.cpp:create_yuva_texture(GrDirectContext*, SkPixmap const&, int)::$_1::operator()(void*) const |
133 | 0 | auto beTex = direct->createBackendTexture(pm, |
134 | 0 | kTopLeft_GrSurfaceOrigin, |
135 | 0 | GrRenderable::kNo, |
136 | 0 | GrProtected::kNo, |
137 | 0 | markFinished, |
138 | 0 | &finishedBECreate, |
139 | 0 | /*label=*/"CreateYuvaTexture"); |
140 | 0 | if (beTex.isValid()) { |
141 | 0 | direct->submit(); |
142 | 0 | while (!finishedBECreate) { |
143 | 0 | direct->checkAsyncWorkCompletion(); |
144 | 0 | } |
145 | 0 | } |
146 | 0 | return beTex; |
147 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper.cpp:create_yuva_texture(GrDirectContext*, SkPixmap const&, int) Unexecuted instantiation: DDLPromiseImageHelper.cpp:create_yuva_texture(GrDirectContext*, SkPixmap const&, int) |
148 | | |
149 | | /* |
150 | | * Create backend textures and upload data to them for all the textures required to satisfy |
151 | | * a single promise image. |
152 | | * For YUV textures this will result in up to 4 actual textures. |
153 | | */ |
154 | | void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext* direct, |
155 | 0 | PromiseImageInfo* info) { |
156 | 0 | if (info->isYUV()) { |
157 | 0 | int numPixmaps = info->yuvaInfo().numPlanes(); |
158 | 0 | for (int j = 0; j < numPixmaps; ++j) { |
159 | 0 | const SkPixmap& yuvPixmap = info->yuvPixmap(j); |
160 | |
|
161 | 0 | PromiseImageCallbackContext* callbackContext = info->callbackContext(j); |
162 | 0 | SkASSERT(callbackContext); |
163 | | |
164 | | // DDL TODO: what should we do with mipmapped YUV images |
165 | 0 | callbackContext->setBackendTexture(create_yuva_texture(direct, yuvPixmap, j)); |
166 | 0 | SkASSERT(callbackContext->promiseImageTexture()); |
167 | 0 | } |
168 | 0 | } else { |
169 | 0 | PromiseImageCallbackContext* callbackContext = info->callbackContext(0); |
170 | 0 | if (!callbackContext) { |
171 | | // This texture would've been too large to fit on the GPU |
172 | 0 | return; |
173 | 0 | } |
174 | | |
175 | 0 | std::unique_ptr<SkPixmap[]> mipLevels = info->normalMipLevels(); |
176 | |
|
177 | 0 | bool finishedBECreate = false; |
178 | 0 | auto markFinished = [](void* context) { |
179 | 0 | *(bool*)context = true; |
180 | 0 | }; Unexecuted instantiation: DDLPromiseImageHelper.cpp:DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext*, DDLPromiseImageHelper::PromiseImageInfo*)::$_0::operator()(void*) const Unexecuted instantiation: DDLPromiseImageHelper.cpp:DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext*, DDLPromiseImageHelper::PromiseImageInfo*)::$_2::operator()(void*) const |
181 | 0 | auto backendTex = direct->createBackendTexture(mipLevels.get(), |
182 | 0 | info->numMipLevels(), |
183 | 0 | kTopLeft_GrSurfaceOrigin, |
184 | 0 | GrRenderable::kNo, |
185 | 0 | GrProtected::kNo, |
186 | 0 | markFinished, |
187 | 0 | &finishedBECreate, |
188 | 0 | /*label=*/"CreateBETexturesForPromiseImage"); |
189 | 0 | SkASSERT(backendTex.isValid()); |
190 | 0 | direct->submit(); |
191 | 0 | while (!finishedBECreate) { |
192 | 0 | direct->checkAsyncWorkCompletion(); |
193 | 0 | } |
194 | |
|
195 | 0 | callbackContext->setBackendTexture(backendTex); |
196 | 0 | } |
197 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext*, DDLPromiseImageHelper::PromiseImageInfo*) Unexecuted instantiation: DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext*, DDLPromiseImageHelper::PromiseImageInfo*) |
198 | | |
199 | 0 | void DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(PromiseImageInfo* info) { |
200 | 0 | if (info->isYUV()) { |
201 | 0 | int numPixmaps = info->yuvaInfo().numPlanes(); |
202 | 0 | for (int j = 0; j < numPixmaps; ++j) { |
203 | 0 | PromiseImageCallbackContext* callbackContext = info->callbackContext(j); |
204 | 0 | SkASSERT(callbackContext); |
205 | |
|
206 | 0 | callbackContext->destroyBackendTexture(); |
207 | 0 | SkASSERT(!callbackContext->promiseImageTexture()); |
208 | 0 | } |
209 | 0 | } else { |
210 | 0 | PromiseImageCallbackContext* callbackContext = info->callbackContext(0); |
211 | 0 | if (!callbackContext) { |
212 | | // This texture would've been too large to fit on the GPU |
213 | 0 | return; |
214 | 0 | } |
215 | | |
216 | 0 | callbackContext->destroyBackendTexture(); |
217 | 0 | SkASSERT(!callbackContext->promiseImageTexture()); |
218 | 0 | } |
219 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(DDLPromiseImageHelper::PromiseImageInfo*) Unexecuted instantiation: DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(DDLPromiseImageHelper::PromiseImageInfo*) |
220 | | |
221 | 0 | void DDLPromiseImageHelper::createCallbackContexts(GrDirectContext* direct) { |
222 | 0 | const GrCaps* caps = direct->priv().caps(); |
223 | 0 | const int maxDimension = caps->maxTextureSize(); |
224 | |
|
225 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
226 | 0 | PromiseImageInfo& info = fImageInfo[i]; |
227 | |
|
228 | 0 | if (info.isYUV()) { |
229 | 0 | int numPixmaps = info.yuvaInfo().numPlanes(); |
230 | |
|
231 | 0 | for (int j = 0; j < numPixmaps; ++j) { |
232 | 0 | const SkPixmap& yuvPixmap = info.yuvPixmap(j); |
233 | |
|
234 | 0 | GrBackendFormat backendFormat = direct->defaultBackendFormat(yuvPixmap.colorType(), |
235 | 0 | GrRenderable::kNo); |
236 | |
|
237 | 0 | sk_sp<PromiseImageCallbackContext> callbackContext( |
238 | 0 | new PromiseImageCallbackContext(direct, backendFormat)); |
239 | |
|
240 | 0 | info.setCallbackContext(j, std::move(callbackContext)); |
241 | 0 | } |
242 | 0 | } else { |
243 | 0 | const SkBitmap& baseLevel = info.baseLevel(); |
244 | | |
245 | | // TODO: explicitly mark the PromiseImageInfo as too big and check in uploadAllToGPU |
246 | 0 | if (maxDimension < std::max(baseLevel.width(), baseLevel.height())) { |
247 | | // This won't fit on the GPU. Fallback to a raster-backed image per tile. |
248 | 0 | continue; |
249 | 0 | } |
250 | | |
251 | 0 | GrBackendFormat backendFormat = direct->defaultBackendFormat(baseLevel.colorType(), |
252 | 0 | GrRenderable::kNo); |
253 | 0 | if (!caps->isFormatTexturable(backendFormat, GrTextureType::k2D)) { |
254 | 0 | continue; |
255 | 0 | } |
256 | | |
257 | 0 | sk_sp<PromiseImageCallbackContext> callbackContext( |
258 | 0 | new PromiseImageCallbackContext(direct, backendFormat)); |
259 | |
|
260 | 0 | info.setCallbackContext(0, std::move(callbackContext)); |
261 | 0 | } |
262 | 0 | } |
263 | 0 | } |
264 | | |
265 | 0 | void DDLPromiseImageHelper::uploadAllToGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) { |
266 | 0 | if (taskGroup) { |
267 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
268 | 0 | PromiseImageInfo* info = &fImageInfo[i]; |
269 | |
|
270 | 0 | taskGroup->add([direct, info]() { CreateBETexturesForPromiseImage(direct, info); }); |
271 | 0 | } |
272 | 0 | } else { |
273 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
274 | 0 | CreateBETexturesForPromiseImage(direct, &fImageInfo[i]); |
275 | 0 | } |
276 | 0 | } |
277 | 0 | } |
278 | | |
279 | 0 | void DDLPromiseImageHelper::deleteAllFromGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) { |
280 | 0 | if (taskGroup) { |
281 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
282 | 0 | PromiseImageInfo* info = &fImageInfo[i]; |
283 | |
|
284 | 0 | taskGroup->add([info]() { DeleteBETexturesForPromiseImage(info); }); |
285 | 0 | } |
286 | 0 | } else { |
287 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
288 | 0 | DeleteBETexturesForPromiseImage(&fImageInfo[i]); |
289 | 0 | } |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | | sk_sp<SkPicture> DDLPromiseImageHelper::reinflateSKP( |
294 | | sk_sp<GrContextThreadSafeProxy> threadSafeProxy, |
295 | 0 | SkData* compressedPictureData) { |
296 | 0 | DeserialImageProcContext procContext { std::move(threadSafeProxy), this }; |
297 | |
|
298 | 0 | SkDeserialProcs procs; |
299 | 0 | procs.fImageCtx = (void*) &procContext; |
300 | 0 | procs.fImageProc = CreatePromiseImages; |
301 | |
|
302 | 0 | return SkPicture::MakeFromData(compressedPictureData, &procs); |
303 | 0 | } |
304 | | |
305 | | // This generates promise images to replace the indices in the compressed picture. |
306 | | sk_sp<SkImage> DDLPromiseImageHelper::CreatePromiseImages(const void* rawData, |
307 | | size_t length, |
308 | 0 | void* ctxIn) { |
309 | 0 | DeserialImageProcContext* procContext = static_cast<DeserialImageProcContext*>(ctxIn); |
310 | 0 | DDLPromiseImageHelper* helper = procContext->fHelper; |
311 | |
|
312 | 0 | SkASSERT(length == sizeof(int)); |
313 | |
|
314 | 0 | const int* indexPtr = static_cast<const int*>(rawData); |
315 | 0 | if (!helper->isValidID(*indexPtr)) { |
316 | 0 | return nullptr; |
317 | 0 | } |
318 | | |
319 | 0 | const DDLPromiseImageHelper::PromiseImageInfo& curImage = helper->getInfo(*indexPtr); |
320 | | |
321 | | // If there is no callback context that means 'createCallbackContexts' determined the |
322 | | // texture wouldn't fit on the GPU. Create a bitmap-backed image. |
323 | 0 | if (!curImage.isYUV() && !curImage.callbackContext(0)) { |
324 | 0 | SkASSERT(curImage.baseLevel().isImmutable()); |
325 | 0 | return curImage.baseLevel().asImage(); |
326 | 0 | } |
327 | | |
328 | 0 | SkASSERT(curImage.index() == *indexPtr); |
329 | |
|
330 | 0 | sk_sp<SkImage> image; |
331 | 0 | if (curImage.isYUV()) { |
332 | 0 | GrBackendFormat backendFormats[SkYUVAInfo::kMaxPlanes]; |
333 | 0 | const SkYUVAInfo& yuvaInfo = curImage.yuvaInfo(); |
334 | 0 | void* contexts[SkYUVAInfo::kMaxPlanes] = {nullptr, nullptr, nullptr, nullptr}; |
335 | 0 | int textureCount = yuvaInfo.numPlanes(); |
336 | 0 | for (int i = 0; i < textureCount; ++i) { |
337 | 0 | backendFormats[i] = curImage.backendFormat(i); |
338 | 0 | contexts[i] = curImage.refCallbackContext(i).release(); |
339 | 0 | } |
340 | 0 | GrYUVABackendTextureInfo yuvaBackendTextures( |
341 | 0 | yuvaInfo, backendFormats, skgpu::Mipmapped::kNo, kTopLeft_GrSurfaceOrigin); |
342 | 0 | image = SkImages::PromiseTextureFromYUVA( |
343 | 0 | procContext->fThreadSafeProxy, |
344 | 0 | yuvaBackendTextures, |
345 | 0 | curImage.refOverallColorSpace(), |
346 | 0 | PromiseImageCallbackContext::PromiseImageFulfillProc, |
347 | 0 | PromiseImageCallbackContext::PromiseImageReleaseProc, |
348 | 0 | contexts); |
349 | 0 | if (!image) { |
350 | 0 | return nullptr; |
351 | 0 | } |
352 | 0 | for (int i = 0; i < textureCount; ++i) { |
353 | 0 | curImage.callbackContext(i)->wasAddedToImage(); |
354 | 0 | } |
355 | |
|
356 | 0 | } else { |
357 | 0 | const GrBackendFormat& backendFormat = curImage.backendFormat(0); |
358 | 0 | SkASSERT(backendFormat.isValid()); |
359 | |
|
360 | 0 | image = SkImages::PromiseTextureFrom(procContext->fThreadSafeProxy, |
361 | 0 | backendFormat, |
362 | 0 | curImage.overallDimensions(), |
363 | 0 | curImage.mipmapped(0), |
364 | 0 | GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin, |
365 | 0 | curImage.overallColorType(), |
366 | 0 | curImage.overallAlphaType(), |
367 | 0 | curImage.refOverallColorSpace(), |
368 | 0 | PromiseImageCallbackContext::PromiseImageFulfillProc, |
369 | 0 | PromiseImageCallbackContext::PromiseImageReleaseProc, |
370 | 0 | (void*)curImage.refCallbackContext(0).release()); |
371 | 0 | curImage.callbackContext(0)->wasAddedToImage(); |
372 | 0 | } |
373 | 0 | helper->fPromiseImages.push_back(image); |
374 | 0 | SkASSERT(image); |
375 | 0 | return image; |
376 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::CreatePromiseImages(void const*, unsigned long, void*) Unexecuted instantiation: DDLPromiseImageHelper::CreatePromiseImages(void const*, unsigned long, void*) |
377 | | |
378 | 0 | int DDLPromiseImageHelper::findImage(SkImage* image) const { |
379 | 0 | for (int i = 0; i < fImageInfo.size(); ++i) { |
380 | 0 | if (fImageInfo[i].originalUniqueID() == image->uniqueID()) { // trying to dedup here |
381 | 0 | SkASSERT(fImageInfo[i].index() == i); |
382 | 0 | SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].index())); |
383 | 0 | return i; |
384 | 0 | } |
385 | 0 | } |
386 | 0 | return -1; |
387 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::findImage(SkImage*) const Unexecuted instantiation: DDLPromiseImageHelper::findImage(SkImage*) const |
388 | | |
389 | 0 | int DDLPromiseImageHelper::addImage(SkImage* image) { |
390 | 0 | SkImage_Base* ib = as_IB(image); |
391 | |
|
392 | 0 | SkImageInfo overallII = SkImageInfo::Make(image->width(), image->height(), |
393 | 0 | image->colorType() == kBGRA_8888_SkColorType |
394 | 0 | ? kRGBA_8888_SkColorType |
395 | 0 | : image->colorType(), |
396 | 0 | image->alphaType(), |
397 | 0 | image->refColorSpace()); |
398 | |
|
399 | 0 | PromiseImageInfo& newImageInfo = fImageInfo.emplace_back(fImageInfo.size(), |
400 | 0 | image->uniqueID(), |
401 | 0 | overallII); |
402 | |
|
403 | 0 | auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(ib->refEncodedData()); |
404 | 0 | SkYUVAPixmapInfo yuvaInfo; |
405 | 0 | if (codec && codec->queryYUVAInfo(fSupportedYUVADataTypes, &yuvaInfo)) { |
406 | 0 | auto yuvaPixmaps = SkYUVAPixmaps::Allocate(yuvaInfo); |
407 | 0 | if (!codec->getYUVAPlanes(yuvaPixmaps)) { |
408 | 0 | return -1; |
409 | 0 | } |
410 | 0 | SkASSERT(yuvaPixmaps.isValid()); |
411 | 0 | newImageInfo.setYUVPlanes(std::move(yuvaPixmaps)); |
412 | 0 | } else { |
413 | 0 | sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images |
414 | 0 | if (!rasterImage) { |
415 | 0 | return -1; |
416 | 0 | } |
417 | | |
418 | 0 | SkBitmap tmp; |
419 | 0 | tmp.allocPixels(overallII); |
420 | |
|
421 | 0 | if (!rasterImage->readPixels(nullptr, tmp.pixmap(), 0, 0)) { |
422 | 0 | return -1; |
423 | 0 | } |
424 | | |
425 | 0 | tmp.setImmutable(); |
426 | | |
427 | | // Given how the DDL testing harness works (i.e., only modifying the SkImages w/in an |
428 | | // SKP) we don't know if a given SkImage will require mipmapping. To work around this |
429 | | // we just try to create all the backend textures as mipmapped but, failing that, fall |
430 | | // back to un-mipped. |
431 | 0 | std::unique_ptr<SkMipmap> mipmaps(SkMipmap::Build(tmp.pixmap(), nullptr)); |
432 | |
|
433 | 0 | newImageInfo.setMipLevels(tmp, std::move(mipmaps)); |
434 | 0 | } |
435 | | // In either case newImageInfo's PromiseImageCallbackContext is filled in by uploadAllToGPU |
436 | | |
437 | 0 | return fImageInfo.size()-1; |
438 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::addImage(SkImage*) Unexecuted instantiation: DDLPromiseImageHelper::addImage(SkImage*) |
439 | | |
440 | 0 | int DDLPromiseImageHelper::findOrDefineImage(SkImage* image) { |
441 | 0 | int preExistingID = this->findImage(image); |
442 | 0 | if (preExistingID >= 0) { |
443 | 0 | SkASSERT(this->isValidID(preExistingID)); |
444 | 0 | return preExistingID; |
445 | 0 | } |
446 | | |
447 | 0 | int newID = this->addImage(image); |
448 | 0 | return newID; |
449 | 0 | } Unexecuted instantiation: DDLPromiseImageHelper::findOrDefineImage(SkImage*) Unexecuted instantiation: DDLPromiseImageHelper::findOrDefineImage(SkImage*) |