blob: 9514321b425ee9e3503cc80f72dcb24ae0a06bf5 [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"
Robert Phillipsd5f3c982020-07-07 13:18:47 -040013#include "include/gpu/GrDirectContext.h"
Brian Salomonbd3792d2020-11-10 14:17:58 -050014#include "include/gpu/GrYUVABackendTextures.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040015#include "src/codec/SkCodecImageGenerator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkCachedData.h"
Mike Reed13711eb2020-07-14 17:16:32 -040017#include "src/core/SkMipmap.h"
Robert Phillips923181b2020-02-14 12:36:37 -050018#include "src/core/SkTaskGroup.h"
Adlai Hollera0693042020-10-14 11:23:11 -040019#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/image/SkImage_Base.h"
21#include "src/image/SkImage_GpuYUVA.h"
Robert Phillips96601082018-05-29 16:13:26 -040022
Robert Phillipsf95e2f42020-04-17 16:20:55 -040023DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(int index,
24 uint32_t originalUniqueID,
25 const SkImageInfo& ii)
26 : fIndex(index)
27 , fOriginalUniqueID(originalUniqueID)
28 , fImageInfo(ii) {
29}
30
31DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(PromiseImageInfo&& other)
32 : fIndex(other.fIndex)
33 , fOriginalUniqueID(other.fOriginalUniqueID)
34 , fImageInfo(other.fImageInfo)
35 , fBaseLevel(other.fBaseLevel)
36 , fMipLevels(std::move(other.fMipLevels))
Brian Salomon5660e8b2020-08-25 12:40:32 -040037 , fYUVAPixmaps(std::move(other.fYUVAPixmaps)) {
Brian Salomon0c0b5a62021-01-11 14:40:44 -050038 for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040039 fCallbackContexts[i] = std::move(other.fCallbackContexts[i]);
40 }
41}
42
43DDLPromiseImageHelper::PromiseImageInfo::~PromiseImageInfo() {}
44
John Stilesec9b4aa2020-08-07 13:05:14 -040045std::unique_ptr<SkPixmap[]> DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040046 SkASSERT(!this->isYUV());
47 std::unique_ptr<SkPixmap[]> pixmaps(new SkPixmap[this->numMipLevels()]);
48 pixmaps[0] = fBaseLevel.pixmap();
49 if (fMipLevels) {
50 for (int i = 0; i < fMipLevels->countLevels(); ++i) {
Mike Reed13711eb2020-07-14 17:16:32 -040051 SkMipmap::Level mipLevel;
Robert Phillipsf95e2f42020-04-17 16:20:55 -040052 fMipLevels->getLevel(i, &mipLevel);
53 pixmaps[i+1] = mipLevel.fPixmap;
54 }
55 }
56 return pixmaps;
57}
58
59int DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const {
60 SkASSERT(!this->isYUV());
61 return fMipLevels ? fMipLevels->countLevels()+1 : 1;
62}
63
64void DDLPromiseImageHelper::PromiseImageInfo::setMipLevels(const SkBitmap& baseLevel,
Mike Reed13711eb2020-07-14 17:16:32 -040065 std::unique_ptr<SkMipmap> mipLevels) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040066 fBaseLevel = baseLevel;
67 fMipLevels = std::move(mipLevels);
68}
69
70///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips11c67672020-04-23 15:10:03 -040071PromiseImageCallbackContext::~PromiseImageCallbackContext() {
Brian Salomon96796122021-01-19 12:11:07 -050072 SkASSERT(fDoneCnt == fNumImages);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050073 SkASSERT(!fTotalFulfills || fDoneCnt);
Robert Phillips96601082018-05-29 16:13:26 -040074
Brian Salomon3f4cd772019-01-11 16:03:19 -050075 if (fPromiseImageTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040076 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
Robert Phillips96601082018-05-29 16:13:26 -040077 }
78}
79
Robert Phillips11c67672020-04-23 15:10:03 -040080void PromiseImageCallbackContext::setBackendTexture(const GrBackendTexture& backendTexture) {
Brian Salomon7d88f312019-02-28 10:03:03 -050081 SkASSERT(!fPromiseImageTexture);
Robert Phillips923181b2020-02-14 12:36:37 -050082 SkASSERT(fBackendFormat == backendTexture.getBackendFormat());
Brian Salomon3f4cd772019-01-11 16:03:19 -050083 fPromiseImageTexture = SkPromiseImageTexture::Make(backendTexture);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050084}
85
Robert Phillipsd5f3c982020-07-07 13:18:47 -040086void PromiseImageCallbackContext::destroyBackendTexture() {
87 SkASSERT(!fPromiseImageTexture || fPromiseImageTexture->unique());
88
89 if (fPromiseImageTexture) {
90 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
91 }
92 fPromiseImageTexture = nullptr;
93}
94
Robert Phillips96601082018-05-29 16:13:26 -040095///////////////////////////////////////////////////////////////////////////////////////////////////
96
Robert Phillips0d8722c2021-03-29 13:29:40 -040097sk_sp<SkPicture> DDLPromiseImageHelper::recreateSKP(GrDirectContext* dContext,
98 SkPicture* inputPicture) {
Robert Phillips96601082018-05-29 16:13:26 -040099 SkSerialProcs procs;
100
101 procs.fImageCtx = this;
102 procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> {
103 auto helper = static_cast<DDLPromiseImageHelper*>(ctx);
104
105 int id = helper->findOrDefineImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400106
Robert Phillips6bad7052019-12-16 15:09:57 -0500107 // Even if 'id' is invalid (i.e., -1) write it to the SKP
108 return SkData::MakeWithCopy(&id, sizeof(id));
Robert Phillips96601082018-05-29 16:13:26 -0400109 };
110
Robert Phillips0d8722c2021-03-29 13:29:40 -0400111 sk_sp<SkData> compressedPictureData = inputPicture->serialize(&procs);
112 if (!compressedPictureData) {
113 return nullptr;
114 }
115
116 this->createCallbackContexts(dContext);
117
118 return this->reinflateSKP(dContext->threadSafeProxy(), compressedPictureData.get());
Robert Phillips96601082018-05-29 16:13:26 -0400119}
120
Brian Salomonbd3792d2020-11-10 14:17:58 -0500121static GrBackendTexture create_yuva_texture(GrDirectContext* direct,
122 const SkPixmap& pm,
123 int texIndex) {
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500124 SkASSERT(texIndex >= 0 && texIndex <= 3);
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400125
Greg Danielc1ad77c2020-05-06 11:40:03 -0400126 bool finishedBECreate = false;
127 auto markFinished = [](void* context) {
128 *(bool*)context = true;
129 };
Brian Salomonb5f880a2020-12-07 11:30:16 -0500130 auto beTex = direct->createBackendTexture(pm,
131 kTopLeft_GrSurfaceOrigin,
132 GrRenderable::kNo,
133 GrProtected::kNo,
134 markFinished,
135 &finishedBECreate);
Greg Danielc1ad77c2020-05-06 11:40:03 -0400136 if (beTex.isValid()) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400137 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400138 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400139 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400140 }
141 }
142 return beTex;
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500143}
144
Robert Phillips923181b2020-02-14 12:36:37 -0500145/*
146 * Create backend textures and upload data to them for all the textures required to satisfy
147 * a single promise image.
148 * For YUV textures this will result in up to 4 actual textures.
149 */
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400150void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext* direct,
Robert Phillips923181b2020-02-14 12:36:37 -0500151 PromiseImageInfo* info) {
Robert Phillips923181b2020-02-14 12:36:37 -0500152 if (info->isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500153 int numPixmaps = info->yuvaInfo().numPlanes();
Robert Phillips923181b2020-02-14 12:36:37 -0500154 for (int j = 0; j < numPixmaps; ++j) {
155 const SkPixmap& yuvPixmap = info->yuvPixmap(j);
156
157 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
158 SkASSERT(callbackContext);
159
Robert Phillips4508eb92020-04-15 15:54:34 -0400160 // DDL TODO: what should we do with mipmapped YUV images
Brian Salomonbd3792d2020-11-10 14:17:58 -0500161 callbackContext->setBackendTexture(create_yuva_texture(direct, yuvPixmap, j));
Robert Phillips923181b2020-02-14 12:36:37 -0500162 SkASSERT(callbackContext->promiseImageTexture());
163 }
164 } else {
165 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
166 if (!callbackContext) {
167 // This texture would've been too large to fit on the GPU
168 return;
169 }
170
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400171 std::unique_ptr<SkPixmap[]> mipLevels = info->normalMipLevels();
Robert Phillips923181b2020-02-14 12:36:37 -0500172
Greg Danielc1ad77c2020-05-06 11:40:03 -0400173 bool finishedBECreate = false;
174 auto markFinished = [](void* context) {
175 *(bool*)context = true;
176 };
Brian Salomonb5f880a2020-12-07 11:30:16 -0500177 auto backendTex = direct->createBackendTexture(mipLevels.get(),
178 info->numMipLevels(),
179 kTopLeft_GrSurfaceOrigin,
180 GrRenderable::kNo,
181 GrProtected::kNo,
182 markFinished,
183 &finishedBECreate);
Robert Phillips923181b2020-02-14 12:36:37 -0500184 SkASSERT(backendTex.isValid());
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400185 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400186 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400187 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400188 }
Robert Phillips923181b2020-02-14 12:36:37 -0500189
190 callbackContext->setBackendTexture(backendTex);
191 }
192}
193
Brian Salomonbd3792d2020-11-10 14:17:58 -0500194void DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(PromiseImageInfo* info) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500195 if (info->isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500196 int numPixmaps = info->yuvaInfo().numPlanes();
Robert Phillips19f466d2020-02-26 10:27:07 -0500197 for (int j = 0; j < numPixmaps; ++j) {
198 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
199 SkASSERT(callbackContext);
200
201 callbackContext->destroyBackendTexture();
202 SkASSERT(!callbackContext->promiseImageTexture());
203 }
204 } else {
205 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
206 if (!callbackContext) {
207 // This texture would've been too large to fit on the GPU
208 return;
209 }
210
211 callbackContext->destroyBackendTexture();
212 SkASSERT(!callbackContext->promiseImageTexture());
213 }
214}
215
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400216void DDLPromiseImageHelper::createCallbackContexts(GrDirectContext* direct) {
217 const GrCaps* caps = direct->priv().caps();
Robert Phillips923181b2020-02-14 12:36:37 -0500218 const int maxDimension = caps->maxTextureSize();
219
220 for (int i = 0; i < fImageInfo.count(); ++i) {
221 PromiseImageInfo& info = fImageInfo[i];
222
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400223 if (info.isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500224 int numPixmaps = info.yuvaInfo().numPlanes();
Robert Phillips923181b2020-02-14 12:36:37 -0500225
Jim Van Verth8f11e432018-10-18 14:36:59 -0400226 for (int j = 0; j < numPixmaps; ++j) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400227 const SkPixmap& yuvPixmap = info.yuvPixmap(j);
Robert Phillips96601082018-05-29 16:13:26 -0400228
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400229 GrBackendFormat backendFormat = direct->defaultBackendFormat(yuvPixmap.colorType(),
230 GrRenderable::kNo);
Robert Phillips923181b2020-02-14 12:36:37 -0500231
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400232 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400233 new PromiseImageCallbackContext(direct, backendFormat));
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500234
Robert Phillips923181b2020-02-14 12:36:37 -0500235 info.setCallbackContext(j, std::move(callbackContext));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400236 }
237 } else {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400238 const SkBitmap& baseLevel = info.baseLevel();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400239
Robert Phillips923181b2020-02-14 12:36:37 -0500240 // TODO: explicitly mark the PromiseImageInfo as too big and check in uploadAllToGPU
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400241 if (maxDimension < std::max(baseLevel.width(), baseLevel.height())) {
Robert Phillips923181b2020-02-14 12:36:37 -0500242 // This won't fit on the GPU. Fallback to a raster-backed image per tile.
243 continue;
244 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400245
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400246 GrBackendFormat backendFormat = direct->defaultBackendFormat(baseLevel.colorType(),
247 GrRenderable::kNo);
Robert Phillips923181b2020-02-14 12:36:37 -0500248 if (!caps->isFormatTexturable(backendFormat)) {
249 continue;
250 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400251
Robert Phillips923181b2020-02-14 12:36:37 -0500252 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400253 new PromiseImageCallbackContext(direct, backendFormat));
Robert Phillips923181b2020-02-14 12:36:37 -0500254
255 info.setCallbackContext(0, std::move(callbackContext));
256 }
257 }
258}
259
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400260void DDLPromiseImageHelper::uploadAllToGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips923181b2020-02-14 12:36:37 -0500261 if (taskGroup) {
262 for (int i = 0; i < fImageInfo.count(); ++i) {
263 PromiseImageInfo* info = &fImageInfo[i];
264
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400265 taskGroup->add([direct, info]() { CreateBETexturesForPromiseImage(direct, info); });
Robert Phillips923181b2020-02-14 12:36:37 -0500266 }
267 } else {
268 for (int i = 0; i < fImageInfo.count(); ++i) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400269 CreateBETexturesForPromiseImage(direct, &fImageInfo[i]);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400270 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500271 }
272}
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400273
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400274void DDLPromiseImageHelper::deleteAllFromGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500275 if (taskGroup) {
276 for (int i = 0; i < fImageInfo.count(); ++i) {
277 PromiseImageInfo* info = &fImageInfo[i];
278
Brian Salomonbd3792d2020-11-10 14:17:58 -0500279 taskGroup->add([info]() { DeleteBETexturesForPromiseImage(info); });
Robert Phillips19f466d2020-02-26 10:27:07 -0500280 }
281 } else {
282 for (int i = 0; i < fImageInfo.count(); ++i) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500283 DeleteBETexturesForPromiseImage(&fImageInfo[i]);
Robert Phillips19f466d2020-02-26 10:27:07 -0500284 }
285 }
286}
287
Robert Phillips96601082018-05-29 16:13:26 -0400288sk_sp<SkPicture> DDLPromiseImageHelper::reinflateSKP(
Adlai Holler55aaefe2021-03-03 16:12:56 -0700289 sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
Robert Phillips0d8722c2021-03-29 13:29:40 -0400290 SkData* compressedPictureData) {
291 DeserialImageProcContext procContext { std::move(threadSafeProxy), this };
Robert Phillips96601082018-05-29 16:13:26 -0400292
293 SkDeserialProcs procs;
Adlai Holler55aaefe2021-03-03 16:12:56 -0700294 procs.fImageCtx = (void*) &procContext;
Robert Phillips923181b2020-02-14 12:36:37 -0500295 procs.fImageProc = CreatePromiseImages;
Robert Phillips96601082018-05-29 16:13:26 -0400296
297 return SkPicture::MakeFromData(compressedPictureData, &procs);
298}
299
Robert Phillips0d8722c2021-03-29 13:29:40 -0400300// This generates promise images to replace the indices in the compressed picture.
Robert Phillips923181b2020-02-14 12:36:37 -0500301sk_sp<SkImage> DDLPromiseImageHelper::CreatePromiseImages(const void* rawData,
Robert Phillips0d8722c2021-03-29 13:29:40 -0400302 size_t length,
303 void* ctxIn) {
Adlai Holler55aaefe2021-03-03 16:12:56 -0700304 DeserialImageProcContext* procContext = static_cast<DeserialImageProcContext*>(ctxIn);
Robert Phillips0d8722c2021-03-29 13:29:40 -0400305 DDLPromiseImageHelper* helper = procContext->fHelper;
Robert Phillips96601082018-05-29 16:13:26 -0400306
307 SkASSERT(length == sizeof(int));
308
309 const int* indexPtr = static_cast<const int*>(rawData);
Robert Phillips6bad7052019-12-16 15:09:57 -0500310 if (!helper->isValidID(*indexPtr)) {
311 return nullptr;
312 }
Robert Phillips96601082018-05-29 16:13:26 -0400313
314 const DDLPromiseImageHelper::PromiseImageInfo& curImage = helper->getInfo(*indexPtr);
315
Robert Phillips923181b2020-02-14 12:36:37 -0500316 // If there is no callback context that means 'createCallbackContexts' determined the
Robert Phillips0d8722c2021-03-29 13:29:40 -0400317 // texture wouldn't fit on the GPU. Create a bitmap-backed image.
Robert Phillips923181b2020-02-14 12:36:37 -0500318 if (!curImage.isYUV() && !curImage.callbackContext(0)) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400319 SkASSERT(curImage.baseLevel().isImmutable());
Mike Reeddc607e32020-12-23 11:50:36 -0500320 return curImage.baseLevel().asImage();
Robert Phillips96601082018-05-29 16:13:26 -0400321 }
Robert Phillips923181b2020-02-14 12:36:37 -0500322
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400323 SkASSERT(curImage.index() == *indexPtr);
Robert Phillips96601082018-05-29 16:13:26 -0400324
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400325 sk_sp<SkImage> image;
326 if (curImage.isYUV()) {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500327 GrBackendFormat backendFormats[SkYUVAInfo::kMaxPlanes];
Brian Salomonbd3792d2020-11-10 14:17:58 -0500328 const SkYUVAInfo& yuvaInfo = curImage.yuvaInfo();
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500329 void* contexts[SkYUVAInfo::kMaxPlanes] = {nullptr, nullptr, nullptr, nullptr};
Brian Salomonbd3792d2020-11-10 14:17:58 -0500330 int textureCount = yuvaInfo.numPlanes();
Jim Van Verth8f11e432018-10-18 14:36:59 -0400331 for (int i = 0; i < textureCount; ++i) {
Robert Phillips923181b2020-02-14 12:36:37 -0500332 backendFormats[i] = curImage.backendFormat(i);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400333 contexts[i] = curImage.refCallbackContext(i).release();
334 }
Brian Salomonbd3792d2020-11-10 14:17:58 -0500335 GrYUVABackendTextureInfo yuvaBackendTextures(yuvaInfo,
336 backendFormats,
337 GrMipmapped::kNo,
338 kTopLeft_GrSurfaceOrigin);
Adlai Holler55aaefe2021-03-03 16:12:56 -0700339 image = SkImage::MakePromiseYUVATexture(
340 procContext->fThreadSafeProxy,
341 yuvaBackendTextures,
342 curImage.refOverallColorSpace(),
343 PromiseImageCallbackContext::PromiseImageFulfillProc,
344 PromiseImageCallbackContext::PromiseImageReleaseProc,
345 contexts);
Brian Salomon72068172020-12-17 09:38:59 -0500346 if (!image) {
347 return nullptr;
348 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500349 for (int i = 0; i < textureCount; ++i) {
350 curImage.callbackContext(i)->wasAddedToImage();
351 }
Robert Phillips193c4212019-03-04 12:18:53 -0500352
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400353 } else {
John Stiles31954bf2020-08-07 17:35:54 -0400354 const GrBackendFormat& backendFormat = curImage.backendFormat(0);
Brian Salomonf391d0f2018-12-14 09:18:50 -0500355 SkASSERT(backendFormat.isValid());
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400356
Adlai Holler55aaefe2021-03-03 16:12:56 -0700357 image = SkImage::MakePromiseTexture(procContext->fThreadSafeProxy,
358 backendFormat,
359 curImage.overallDimensions(),
360 curImage.mipMapped(0),
361 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
362 curImage.overallColorType(),
363 curImage.overallAlphaType(),
364 curImage.refOverallColorSpace(),
365 PromiseImageCallbackContext::PromiseImageFulfillProc,
366 PromiseImageCallbackContext::PromiseImageReleaseProc,
367 (void*)curImage.refCallbackContext(0).release());
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500368 curImage.callbackContext(0)->wasAddedToImage();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400369 }
Robert Phillips0d8722c2021-03-29 13:29:40 -0400370 helper->fPromiseImages.push_back(image);
Robert Phillips96601082018-05-29 16:13:26 -0400371 SkASSERT(image);
372 return image;
373}
374
375int DDLPromiseImageHelper::findImage(SkImage* image) const {
376 for (int i = 0; i < fImageInfo.count(); ++i) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400377 if (fImageInfo[i].originalUniqueID() == image->uniqueID()) { // trying to dedup here
378 SkASSERT(fImageInfo[i].index() == i);
379 SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].index()));
Robert Phillips96601082018-05-29 16:13:26 -0400380 return i;
381 }
382 }
383 return -1;
384}
385
386int DDLPromiseImageHelper::addImage(SkImage* image) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400387 SkImage_Base* ib = as_IB(image);
Robert Phillips96601082018-05-29 16:13:26 -0400388
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400389 SkImageInfo overallII = SkImageInfo::Make(image->width(), image->height(),
Robert Phillips13371a12019-05-13 15:59:10 -0400390 image->colorType() == kBGRA_8888_SkColorType
391 ? kRGBA_8888_SkColorType
392 : image->colorType(),
393 image->alphaType(),
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400394 image->refColorSpace());
Robert Phillips96601082018-05-29 16:13:26 -0400395
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400396 PromiseImageInfo& newImageInfo = fImageInfo.emplace_back(fImageInfo.count(),
397 image->uniqueID(),
398 overallII);
Robert Phillips96601082018-05-29 16:13:26 -0400399
Brian Salomonefb5f072020-07-28 21:06:43 -0400400 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(ib->refEncodedData());
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400401 SkYUVAPixmapInfo yuvaInfo;
Brian Salomon59c60b02020-09-01 15:01:15 -0400402 if (codec && codec->queryYUVAInfo(fSupportedYUVADataTypes, &yuvaInfo)) {
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400403 auto yuvaPixmaps = SkYUVAPixmaps::Allocate(yuvaInfo);
Robert Phillips9c2ab4c2021-02-02 10:01:59 -0500404 if (!codec->getYUVAPlanes(yuvaPixmaps)) {
405 return -1;
406 }
Brian Salomon5660e8b2020-08-25 12:40:32 -0400407 SkASSERT(yuvaPixmaps.isValid());
408 newImageInfo.setYUVPlanes(std::move(yuvaPixmaps));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400409 } else {
410 sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
Robert Phillipse84bffc2019-12-16 11:22:17 -0500411 if (!rasterImage) {
412 return -1;
413 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400414
415 SkBitmap tmp;
416 tmp.allocPixels(overallII);
417
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400418 if (!rasterImage->readPixels(nullptr, tmp.pixmap(), 0, 0)) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400419 return -1;
420 }
421
422 tmp.setImmutable();
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400423
424 // Given how the DDL testing harness works (i.e., only modifying the SkImages w/in an
425 // SKP) we don't know if a given SkImage will require mipmapping. To work around this
426 // we just try to create all the backend textures as mipmapped but, failing that, fall
427 // back to un-mipped.
Mike Reed13711eb2020-07-14 17:16:32 -0400428 std::unique_ptr<SkMipmap> mipmaps(SkMipmap::Build(tmp.pixmap(), nullptr));
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400429
430 newImageInfo.setMipLevels(tmp, std::move(mipmaps));
Robert Phillips96601082018-05-29 16:13:26 -0400431 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400432 // In either case newImageInfo's PromiseImageCallbackContext is filled in by uploadAllToGPU
Robert Phillips96601082018-05-29 16:13:26 -0400433
434 return fImageInfo.count()-1;
435}
436
437int DDLPromiseImageHelper::findOrDefineImage(SkImage* image) {
438 int preExistingID = this->findImage(image);
439 if (preExistingID >= 0) {
440 SkASSERT(this->isValidID(preExistingID));
441 return preExistingID;
442 }
443
444 int newID = this->addImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400445 return newID;
446}