blob: e87c1f6ca042db4208cedf4b2d89f6b03344c64b [file] [log] [blame]
Robert Phillips96601082018-05-29 16:13:26 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tools/DDLPromiseImageHelper.h"
Robert Phillips96601082018-05-29 16:13:26 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkDeferredDisplayListRecorder.h"
Robert Phillips66944402019-09-30 13:21:25 -040011#include "include/core/SkPicture.h"
12#include "include/core/SkSerialProcs.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkYUVAIndex.h"
14#include "include/core/SkYUVASizeInfo.h"
Robert Phillipsd5f3c982020-07-07 13:18:47 -040015#include "include/gpu/GrDirectContext.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040016#include "src/codec/SkCodecImageGenerator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/core/SkCachedData.h"
Mike Reed13711eb2020-07-14 17:16:32 -040018#include "src/core/SkMipmap.h"
Robert Phillips923181b2020-02-14 12:36:37 -050019#include "src/core/SkTaskGroup.h"
20#include "src/gpu/GrContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/image/SkImage_Base.h"
22#include "src/image/SkImage_GpuYUVA.h"
Robert Phillips96601082018-05-29 16:13:26 -040023
Robert Phillipsf95e2f42020-04-17 16:20:55 -040024DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(int index,
25 uint32_t originalUniqueID,
26 const SkImageInfo& ii)
27 : fIndex(index)
28 , fOriginalUniqueID(originalUniqueID)
29 , fImageInfo(ii) {
30}
31
32DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(PromiseImageInfo&& other)
33 : fIndex(other.fIndex)
34 , fOriginalUniqueID(other.fOriginalUniqueID)
35 , fImageInfo(other.fImageInfo)
36 , fBaseLevel(other.fBaseLevel)
37 , fMipLevels(std::move(other.fMipLevels))
Brian Salomon5660e8b2020-08-25 12:40:32 -040038 , fYUVAPixmaps(std::move(other.fYUVAPixmaps)) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040039 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040040 fCallbackContexts[i] = std::move(other.fCallbackContexts[i]);
41 }
Brian Salomon5660e8b2020-08-25 12:40:32 -040042 std::copy_n(other.fYUVAIndices, SkYUVAIndex::kIndexCount, fYUVAIndices);
Robert Phillipsf95e2f42020-04-17 16:20:55 -040043}
44
45DDLPromiseImageHelper::PromiseImageInfo::~PromiseImageInfo() {}
46
John Stilesec9b4aa2020-08-07 13:05:14 -040047std::unique_ptr<SkPixmap[]> DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040048 SkASSERT(!this->isYUV());
49 std::unique_ptr<SkPixmap[]> pixmaps(new SkPixmap[this->numMipLevels()]);
50 pixmaps[0] = fBaseLevel.pixmap();
51 if (fMipLevels) {
52 for (int i = 0; i < fMipLevels->countLevels(); ++i) {
Mike Reed13711eb2020-07-14 17:16:32 -040053 SkMipmap::Level mipLevel;
Robert Phillipsf95e2f42020-04-17 16:20:55 -040054 fMipLevels->getLevel(i, &mipLevel);
55 pixmaps[i+1] = mipLevel.fPixmap;
56 }
57 }
58 return pixmaps;
59}
60
61int DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const {
62 SkASSERT(!this->isYUV());
63 return fMipLevels ? fMipLevels->countLevels()+1 : 1;
64}
65
66void DDLPromiseImageHelper::PromiseImageInfo::setMipLevels(const SkBitmap& baseLevel,
Mike Reed13711eb2020-07-14 17:16:32 -040067 std::unique_ptr<SkMipmap> mipLevels) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040068 fBaseLevel = baseLevel;
69 fMipLevels = std::move(mipLevels);
70}
71
Brian Salomon5660e8b2020-08-25 12:40:32 -040072void DDLPromiseImageHelper::PromiseImageInfo::initYUVAIndices() {
73 SkYUVASizeInfo unusedSizeInfo;
Brian Salomonbe0e42c2020-08-27 11:00:04 -040074 fYUVAPixmaps.toLegacy(&unusedSizeInfo, fYUVAIndices);
Brian Salomon5660e8b2020-08-25 12:40:32 -040075 // We can wind up with alpha pixmaps that become red textures. If so, update YUVA indices.
76 // Note: This goes away when we start creating YUVA images using SkYUVAInfo.
77 for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
78 if (fYUVAIndices[i].fIndex >= 0) {
79 int textureIdx = fYUVAIndices[i].fIndex;
80 const auto& format = fCallbackContexts[textureIdx]->backendFormat();
81 if (fYUVAIndices[i].fChannel == SkColorChannel::kA &&
82 format.channelMask() == SkColorChannelFlag::kRed_SkColorChannelFlag) {
83 fYUVAIndices[i].fChannel = SkColorChannel::kR;
84 }
Brian Salomonefb5f072020-07-28 21:06:43 -040085 }
Brian Salomonefb5f072020-07-28 21:06:43 -040086 }
87}
88
Robert Phillipsf95e2f42020-04-17 16:20:55 -040089///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips11c67672020-04-23 15:10:03 -040090PromiseImageCallbackContext::~PromiseImageCallbackContext() {
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050091 SkASSERT(fDoneCnt == fNumImages);
92 SkASSERT(!fUnreleasedFulfills);
93 SkASSERT(fTotalReleases == fTotalFulfills);
94 SkASSERT(!fTotalFulfills || fDoneCnt);
Robert Phillips96601082018-05-29 16:13:26 -040095
Brian Salomon3f4cd772019-01-11 16:03:19 -050096 if (fPromiseImageTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040097 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
Robert Phillips96601082018-05-29 16:13:26 -040098 }
99}
100
Robert Phillips11c67672020-04-23 15:10:03 -0400101void PromiseImageCallbackContext::setBackendTexture(const GrBackendTexture& backendTexture) {
Brian Salomon7d88f312019-02-28 10:03:03 -0500102 SkASSERT(!fPromiseImageTexture);
Robert Phillips923181b2020-02-14 12:36:37 -0500103 SkASSERT(fBackendFormat == backendTexture.getBackendFormat());
Brian Salomon3f4cd772019-01-11 16:03:19 -0500104 fPromiseImageTexture = SkPromiseImageTexture::Make(backendTexture);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500105}
106
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400107void PromiseImageCallbackContext::destroyBackendTexture() {
108 SkASSERT(!fPromiseImageTexture || fPromiseImageTexture->unique());
109
110 if (fPromiseImageTexture) {
111 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
112 }
113 fPromiseImageTexture = nullptr;
114}
115
Robert Phillips96601082018-05-29 16:13:26 -0400116///////////////////////////////////////////////////////////////////////////////////////////////////
117
118sk_sp<SkData> DDLPromiseImageHelper::deflateSKP(const SkPicture* inputPicture) {
119 SkSerialProcs procs;
120
121 procs.fImageCtx = this;
122 procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> {
123 auto helper = static_cast<DDLPromiseImageHelper*>(ctx);
124
125 int id = helper->findOrDefineImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400126
Robert Phillips6bad7052019-12-16 15:09:57 -0500127 // Even if 'id' is invalid (i.e., -1) write it to the SKP
128 return SkData::MakeWithCopy(&id, sizeof(id));
Robert Phillips96601082018-05-29 16:13:26 -0400129 };
130
131 return inputPicture->serialize(&procs);
132}
133
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400134static GrBackendTexture create_yuva_texture(GrDirectContext* direct, const SkPixmap& pm,
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500135 const SkYUVAIndex yuvaIndices[4], int texIndex) {
136 SkASSERT(texIndex >= 0 && texIndex <= 3);
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400137
138#ifdef SK_DEBUG
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500139 int channelCount = 0;
140 for (int i = 0; i < SkYUVAIndex::kIndexCount; ++i) {
141 if (yuvaIndices[i].fIndex == texIndex) {
142 ++channelCount;
143 }
144 }
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500145 if (2 == channelCount) {
Robert Phillipsea1b30b2019-09-19 16:05:48 -0400146 SkASSERT(kR8G8_unorm_SkColorType == pm.colorType());
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500147 }
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400148#endif
Greg Danielc1ad77c2020-05-06 11:40:03 -0400149 bool finishedBECreate = false;
150 auto markFinished = [](void* context) {
151 *(bool*)context = true;
152 };
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400153 auto beTex = direct->createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo,
154 markFinished, &finishedBECreate);
Greg Danielc1ad77c2020-05-06 11:40:03 -0400155 if (beTex.isValid()) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400156 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400157 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400158 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400159 }
160 }
161 return beTex;
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500162}
163
Robert Phillips923181b2020-02-14 12:36:37 -0500164/*
165 * Create backend textures and upload data to them for all the textures required to satisfy
166 * a single promise image.
167 * For YUV textures this will result in up to 4 actual textures.
168 */
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400169void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext* direct,
Robert Phillips923181b2020-02-14 12:36:37 -0500170 PromiseImageInfo* info) {
Robert Phillips923181b2020-02-14 12:36:37 -0500171 if (info->isYUV()) {
172 int numPixmaps;
173 SkAssertResult(SkYUVAIndex::AreValidIndices(info->yuvaIndices(), &numPixmaps));
174 for (int j = 0; j < numPixmaps; ++j) {
175 const SkPixmap& yuvPixmap = info->yuvPixmap(j);
176
177 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
178 SkASSERT(callbackContext);
179
Robert Phillips4508eb92020-04-15 15:54:34 -0400180 // DDL TODO: what should we do with mipmapped YUV images
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400181 callbackContext->setBackendTexture(create_yuva_texture(direct, yuvPixmap,
Robert Phillips923181b2020-02-14 12:36:37 -0500182 info->yuvaIndices(), j));
183 SkASSERT(callbackContext->promiseImageTexture());
184 }
185 } else {
186 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
187 if (!callbackContext) {
188 // This texture would've been too large to fit on the GPU
189 return;
190 }
191
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400192 std::unique_ptr<SkPixmap[]> mipLevels = info->normalMipLevels();
Robert Phillips923181b2020-02-14 12:36:37 -0500193
Greg Danielc1ad77c2020-05-06 11:40:03 -0400194 bool finishedBECreate = false;
195 auto markFinished = [](void* context) {
196 *(bool*)context = true;
197 };
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400198 auto backendTex = direct->createBackendTexture(mipLevels.get(), info->numMipLevels(),
199 GrRenderable::kNo, GrProtected::kNo,
200 markFinished, &finishedBECreate);
Robert Phillips923181b2020-02-14 12:36:37 -0500201 SkASSERT(backendTex.isValid());
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400202 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400203 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400204 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400205 }
Robert Phillips923181b2020-02-14 12:36:37 -0500206
207 callbackContext->setBackendTexture(backendTex);
208 }
209}
210
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400211void DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(GrDirectContext* direct,
Robert Phillips19f466d2020-02-26 10:27:07 -0500212 PromiseImageInfo* info) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500213 if (info->isYUV()) {
214 int numPixmaps;
215 SkAssertResult(SkYUVAIndex::AreValidIndices(info->yuvaIndices(), &numPixmaps));
216 for (int j = 0; j < numPixmaps; ++j) {
217 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
218 SkASSERT(callbackContext);
219
220 callbackContext->destroyBackendTexture();
221 SkASSERT(!callbackContext->promiseImageTexture());
222 }
223 } else {
224 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
225 if (!callbackContext) {
226 // This texture would've been too large to fit on the GPU
227 return;
228 }
229
230 callbackContext->destroyBackendTexture();
231 SkASSERT(!callbackContext->promiseImageTexture());
232 }
233}
234
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400235void DDLPromiseImageHelper::createCallbackContexts(GrDirectContext* direct) {
236 const GrCaps* caps = direct->priv().caps();
Robert Phillips923181b2020-02-14 12:36:37 -0500237 const int maxDimension = caps->maxTextureSize();
238
239 for (int i = 0; i < fImageInfo.count(); ++i) {
240 PromiseImageInfo& info = fImageInfo[i];
241
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400242 if (info.isYUV()) {
Brian Salomon5660e8b2020-08-25 12:40:32 -0400243 int numPixmaps = info.numYUVAPlanes();
Robert Phillips923181b2020-02-14 12:36:37 -0500244
Jim Van Verth8f11e432018-10-18 14:36:59 -0400245 for (int j = 0; j < numPixmaps; ++j) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400246 const SkPixmap& yuvPixmap = info.yuvPixmap(j);
Robert Phillips96601082018-05-29 16:13:26 -0400247
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400248 GrBackendFormat backendFormat = direct->defaultBackendFormat(yuvPixmap.colorType(),
249 GrRenderable::kNo);
Robert Phillips923181b2020-02-14 12:36:37 -0500250
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400251 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400252 new PromiseImageCallbackContext(direct, backendFormat));
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500253
Robert Phillips923181b2020-02-14 12:36:37 -0500254 info.setCallbackContext(j, std::move(callbackContext));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400255 }
Brian Salomon5660e8b2020-08-25 12:40:32 -0400256 info.initYUVAIndices();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400257 } else {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400258 const SkBitmap& baseLevel = info.baseLevel();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400259
Robert Phillips923181b2020-02-14 12:36:37 -0500260 // TODO: explicitly mark the PromiseImageInfo as too big and check in uploadAllToGPU
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400261 if (maxDimension < std::max(baseLevel.width(), baseLevel.height())) {
Robert Phillips923181b2020-02-14 12:36:37 -0500262 // This won't fit on the GPU. Fallback to a raster-backed image per tile.
263 continue;
264 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400265
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400266 GrBackendFormat backendFormat = direct->defaultBackendFormat(baseLevel.colorType(),
267 GrRenderable::kNo);
Robert Phillips923181b2020-02-14 12:36:37 -0500268 if (!caps->isFormatTexturable(backendFormat)) {
269 continue;
270 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400271
Robert Phillips923181b2020-02-14 12:36:37 -0500272 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400273 new PromiseImageCallbackContext(direct, backendFormat));
Robert Phillips923181b2020-02-14 12:36:37 -0500274
275 info.setCallbackContext(0, std::move(callbackContext));
276 }
277 }
278}
279
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400280void DDLPromiseImageHelper::uploadAllToGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips923181b2020-02-14 12:36:37 -0500281 if (taskGroup) {
282 for (int i = 0; i < fImageInfo.count(); ++i) {
283 PromiseImageInfo* info = &fImageInfo[i];
284
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400285 taskGroup->add([direct, info]() { CreateBETexturesForPromiseImage(direct, info); });
Robert Phillips923181b2020-02-14 12:36:37 -0500286 }
287 } else {
288 for (int i = 0; i < fImageInfo.count(); ++i) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400289 CreateBETexturesForPromiseImage(direct, &fImageInfo[i]);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400290 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500291 }
292}
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400293
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400294void DDLPromiseImageHelper::deleteAllFromGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500295 if (taskGroup) {
296 for (int i = 0; i < fImageInfo.count(); ++i) {
297 PromiseImageInfo* info = &fImageInfo[i];
298
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400299 taskGroup->add([direct, info]() { DeleteBETexturesForPromiseImage(direct, info); });
Robert Phillips19f466d2020-02-26 10:27:07 -0500300 }
301 } else {
302 for (int i = 0; i < fImageInfo.count(); ++i) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400303 DeleteBETexturesForPromiseImage(direct, &fImageInfo[i]);
Robert Phillips19f466d2020-02-26 10:27:07 -0500304 }
305 }
306}
307
Robert Phillips96601082018-05-29 16:13:26 -0400308sk_sp<SkPicture> DDLPromiseImageHelper::reinflateSKP(
309 SkDeferredDisplayListRecorder* recorder,
310 SkData* compressedPictureData,
311 SkTArray<sk_sp<SkImage>>* promiseImages) const {
312 PerRecorderContext perRecorderContext { recorder, this, promiseImages };
313
314 SkDeserialProcs procs;
315 procs.fImageCtx = (void*) &perRecorderContext;
Robert Phillips923181b2020-02-14 12:36:37 -0500316 procs.fImageProc = CreatePromiseImages;
Robert Phillips96601082018-05-29 16:13:26 -0400317
318 return SkPicture::MakeFromData(compressedPictureData, &procs);
319}
320
321// This generates promise images to replace the indices in the compressed picture. This
322// reconstitution is performed separately in each thread so we end up with multiple
323// promise images referring to the same GrBackendTexture.
Robert Phillips923181b2020-02-14 12:36:37 -0500324sk_sp<SkImage> DDLPromiseImageHelper::CreatePromiseImages(const void* rawData,
Robert Phillips96601082018-05-29 16:13:26 -0400325 size_t length, void* ctxIn) {
326 PerRecorderContext* perRecorderContext = static_cast<PerRecorderContext*>(ctxIn);
327 const DDLPromiseImageHelper* helper = perRecorderContext->fHelper;
328 SkDeferredDisplayListRecorder* recorder = perRecorderContext->fRecorder;
329
330 SkASSERT(length == sizeof(int));
331
332 const int* indexPtr = static_cast<const int*>(rawData);
Robert Phillips6bad7052019-12-16 15:09:57 -0500333 if (!helper->isValidID(*indexPtr)) {
334 return nullptr;
335 }
Robert Phillips96601082018-05-29 16:13:26 -0400336
337 const DDLPromiseImageHelper::PromiseImageInfo& curImage = helper->getInfo(*indexPtr);
338
Robert Phillips923181b2020-02-14 12:36:37 -0500339 // If there is no callback context that means 'createCallbackContexts' determined the
340 // texture wouldn't fit on the GPU. Create a separate bitmap-backed image for each thread.
341 if (!curImage.isYUV() && !curImage.callbackContext(0)) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400342 SkASSERT(curImage.baseLevel().isImmutable());
343 return SkImage::MakeFromBitmap(curImage.baseLevel());
Robert Phillips96601082018-05-29 16:13:26 -0400344 }
Robert Phillips923181b2020-02-14 12:36:37 -0500345
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400346 SkASSERT(curImage.index() == *indexPtr);
Robert Phillips96601082018-05-29 16:13:26 -0400347
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400348 sk_sp<SkImage> image;
349 if (curImage.isYUV()) {
Jim Van Verthe24b5872018-10-29 16:26:02 -0400350 GrBackendFormat backendFormats[SkYUVASizeInfo::kMaxCount];
351 void* contexts[SkYUVASizeInfo::kMaxCount] = { nullptr, nullptr, nullptr, nullptr };
352 SkISize sizes[SkYUVASizeInfo::kMaxCount];
Jim Van Verth8f11e432018-10-18 14:36:59 -0400353 // TODO: store this value somewhere?
354 int textureCount;
355 SkAssertResult(SkYUVAIndex::AreValidIndices(curImage.yuvaIndices(), &textureCount));
356 for (int i = 0; i < textureCount; ++i) {
Robert Phillips923181b2020-02-14 12:36:37 -0500357 backendFormats[i] = curImage.backendFormat(i);
Brian Salomonf391d0f2018-12-14 09:18:50 -0500358 SkASSERT(backendFormats[i].isValid());
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400359 contexts[i] = curImage.refCallbackContext(i).release();
Jim Van Verthf9f07352018-10-24 10:32:20 -0400360 sizes[i].set(curImage.yuvPixmap(i).width(), curImage.yuvPixmap(i).height());
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400361 }
Jim Van Verthe24b5872018-10-29 16:26:02 -0400362 for (int i = textureCount; i < SkYUVASizeInfo::kMaxCount; ++i) {
Jim Van Verthf9f07352018-10-24 10:32:20 -0400363 sizes[i] = SkISize::MakeEmpty();
Jim Van Verth8f11e432018-10-18 14:36:59 -0400364 }
Jim Van Verthf99a6742018-10-18 16:13:18 +0000365
Brian Salomon0cc57542019-03-08 13:28:46 -0500366 image = recorder->makeYUVAPromiseTexture(
367 curImage.yuvColorSpace(),
368 backendFormats,
369 sizes,
370 curImage.yuvaIndices(),
371 curImage.overallWidth(),
372 curImage.overallHeight(),
373 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
374 curImage.refOverallColorSpace(),
Robert Phillips11c67672020-04-23 15:10:03 -0400375 PromiseImageCallbackContext::PromiseImageFulfillProc,
376 PromiseImageCallbackContext::PromiseImageReleaseProc,
377 PromiseImageCallbackContext::PromiseImageDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500378 contexts,
379 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500380 for (int i = 0; i < textureCount; ++i) {
381 curImage.callbackContext(i)->wasAddedToImage();
382 }
Robert Phillips193c4212019-03-04 12:18:53 -0500383
384#ifdef SK_DEBUG
385 {
386 // By the peekProxy contract this image should not have a single backing proxy so
387 // should return null. The call should also not trigger the conversion to RGBA.
388 SkImage_GpuYUVA* yuva = reinterpret_cast<SkImage_GpuYUVA*>(image.get());
389 SkASSERT(!yuva->peekProxy());
390 SkASSERT(!yuva->peekProxy()); // the first call didn't force a conversion to RGBA
391 }
392#endif
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400393 } else {
John Stiles31954bf2020-08-07 17:35:54 -0400394 const GrBackendFormat& backendFormat = curImage.backendFormat(0);
Brian Salomonf391d0f2018-12-14 09:18:50 -0500395 SkASSERT(backendFormat.isValid());
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400396
397 // Each DDL recorder gets its own ref on the promise callback context for the
398 // promise images it creates.
Brian Salomon0cc57542019-03-08 13:28:46 -0500399 image = recorder->makePromiseTexture(
400 backendFormat,
401 curImage.overallWidth(),
402 curImage.overallHeight(),
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400403 curImage.mipMapped(0),
Brian Salomon0cc57542019-03-08 13:28:46 -0500404 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
405 curImage.overallColorType(),
406 curImage.overallAlphaType(),
407 curImage.refOverallColorSpace(),
Robert Phillips11c67672020-04-23 15:10:03 -0400408 PromiseImageCallbackContext::PromiseImageFulfillProc,
409 PromiseImageCallbackContext::PromiseImageReleaseProc,
410 PromiseImageCallbackContext::PromiseImageDoneProc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500411 (void*)curImage.refCallbackContext(0).release(),
412 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500413 curImage.callbackContext(0)->wasAddedToImage();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400414 }
Robert Phillips96601082018-05-29 16:13:26 -0400415 perRecorderContext->fPromiseImages->push_back(image);
416 SkASSERT(image);
417 return image;
418}
419
420int DDLPromiseImageHelper::findImage(SkImage* image) const {
421 for (int i = 0; i < fImageInfo.count(); ++i) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400422 if (fImageInfo[i].originalUniqueID() == image->uniqueID()) { // trying to dedup here
423 SkASSERT(fImageInfo[i].index() == i);
424 SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].index()));
Robert Phillips96601082018-05-29 16:13:26 -0400425 return i;
426 }
427 }
428 return -1;
429}
430
431int DDLPromiseImageHelper::addImage(SkImage* image) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400432 SkImage_Base* ib = as_IB(image);
Robert Phillips96601082018-05-29 16:13:26 -0400433
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400434 SkImageInfo overallII = SkImageInfo::Make(image->width(), image->height(),
Robert Phillips13371a12019-05-13 15:59:10 -0400435 image->colorType() == kBGRA_8888_SkColorType
436 ? kRGBA_8888_SkColorType
437 : image->colorType(),
438 image->alphaType(),
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400439 image->refColorSpace());
Robert Phillips96601082018-05-29 16:13:26 -0400440
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400441 PromiseImageInfo& newImageInfo = fImageInfo.emplace_back(fImageInfo.count(),
442 image->uniqueID(),
443 overallII);
Robert Phillips96601082018-05-29 16:13:26 -0400444
Brian Salomonefb5f072020-07-28 21:06:43 -0400445 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(ib->refEncodedData());
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400446 SkYUVAPixmapInfo yuvaInfo;
447 if (codec && codec->queryYUVAInfo(&yuvaInfo)) {
448 auto yuvaPixmaps = SkYUVAPixmaps::Allocate(yuvaInfo);
449 SkAssertResult(codec->getYUVAPlanes(yuvaPixmaps));
Brian Salomon5660e8b2020-08-25 12:40:32 -0400450 SkASSERT(yuvaPixmaps.isValid());
451 newImageInfo.setYUVPlanes(std::move(yuvaPixmaps));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400452 } else {
453 sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
Robert Phillipse84bffc2019-12-16 11:22:17 -0500454 if (!rasterImage) {
455 return -1;
456 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400457
458 SkBitmap tmp;
459 tmp.allocPixels(overallII);
460
461 if (!rasterImage->readPixels(tmp.pixmap(), 0, 0)) {
462 return -1;
463 }
464
465 tmp.setImmutable();
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400466
467 // Given how the DDL testing harness works (i.e., only modifying the SkImages w/in an
468 // SKP) we don't know if a given SkImage will require mipmapping. To work around this
469 // we just try to create all the backend textures as mipmapped but, failing that, fall
470 // back to un-mipped.
Mike Reed13711eb2020-07-14 17:16:32 -0400471 std::unique_ptr<SkMipmap> mipmaps(SkMipmap::Build(tmp.pixmap(), nullptr));
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400472
473 newImageInfo.setMipLevels(tmp, std::move(mipmaps));
Robert Phillips96601082018-05-29 16:13:26 -0400474 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400475 // In either case newImageInfo's PromiseImageCallbackContext is filled in by uploadAllToGPU
Robert Phillips96601082018-05-29 16:13:26 -0400476
477 return fImageInfo.count()-1;
478}
479
480int DDLPromiseImageHelper::findOrDefineImage(SkImage* image) {
481 int preExistingID = this->findImage(image);
482 if (preExistingID >= 0) {
483 SkASSERT(this->isValidID(preExistingID));
484 return preExistingID;
485 }
486
487 int newID = this->addImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400488 return newID;
489}