blob: f3232c0b41233b1baf635a688516621c00feea10 [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
Robert Phillips66944402019-09-30 13:21:25 -040010#include "include/core/SkPicture.h"
11#include "include/core/SkSerialProcs.h"
Kevin Lubick0bff57e2023-06-09 14:29:17 -040012#include "include/gpu/GrContextThreadSafeProxy.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"
Kevin Lubick77472bf2023-03-24 07:11:17 -040015#include "include/gpu/ganesh/SkImageGanesh.h"
Kevin Lubickeb981252023-06-13 07:51:26 -040016#include "include/private/chromium/SkImageChromium.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040017#include "src/codec/SkCodecImageGenerator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/core/SkCachedData.h"
Mike Reed13711eb2020-07-14 17:16:32 -040019#include "src/core/SkMipmap.h"
Robert Phillips923181b2020-02-14 12:36:37 -050020#include "src/core/SkTaskGroup.h"
Kevin Lubick502553f2022-11-28 12:42:38 -050021#include "src/gpu/ganesh/GrCaps.h"
Greg Daniel719239c2022-04-07 11:20:24 -040022#include "src/gpu/ganesh/GrDirectContextPriv.h"
Kevin Lubickbf174bc2023-03-27 11:24:20 -040023#include "src/gpu/ganesh/image/SkImage_GaneshYUVA.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/image/SkImage_Base.h"
Robert Phillips96601082018-05-29 16:13:26 -040025
Robert Phillipsf95e2f42020-04-17 16:20:55 -040026DDLPromiseImageHelper::PromiseImageInfo::PromiseImageInfo(int index,
27 uint32_t originalUniqueID,
28 const SkImageInfo& ii)
29 : fIndex(index)
30 , fOriginalUniqueID(originalUniqueID)
31 , fImageInfo(ii) {
32}
33
34DDLPromiseImageHelper::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))
Brian Salomon5660e8b2020-08-25 12:40:32 -040040 , fYUVAPixmaps(std::move(other.fYUVAPixmaps)) {
Brian Salomon0c0b5a62021-01-11 14:40:44 -050041 for (int i = 0; i < SkYUVAInfo::kMaxPlanes; ++i) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040042 fCallbackContexts[i] = std::move(other.fCallbackContexts[i]);
43 }
44}
45
46DDLPromiseImageHelper::PromiseImageInfo::~PromiseImageInfo() {}
47
John Stilesec9b4aa2020-08-07 13:05:14 -040048std::unique_ptr<SkPixmap[]> DDLPromiseImageHelper::PromiseImageInfo::normalMipLevels() const {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040049 SkASSERT(!this->isYUV());
50 std::unique_ptr<SkPixmap[]> pixmaps(new SkPixmap[this->numMipLevels()]);
51 pixmaps[0] = fBaseLevel.pixmap();
52 if (fMipLevels) {
53 for (int i = 0; i < fMipLevels->countLevels(); ++i) {
Mike Reed13711eb2020-07-14 17:16:32 -040054 SkMipmap::Level mipLevel;
Robert Phillipsf95e2f42020-04-17 16:20:55 -040055 fMipLevels->getLevel(i, &mipLevel);
56 pixmaps[i+1] = mipLevel.fPixmap;
57 }
58 }
59 return pixmaps;
60}
61
62int DDLPromiseImageHelper::PromiseImageInfo::numMipLevels() const {
63 SkASSERT(!this->isYUV());
64 return fMipLevels ? fMipLevels->countLevels()+1 : 1;
65}
66
67void DDLPromiseImageHelper::PromiseImageInfo::setMipLevels(const SkBitmap& baseLevel,
Mike Reed13711eb2020-07-14 17:16:32 -040068 std::unique_ptr<SkMipmap> mipLevels) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -040069 fBaseLevel = baseLevel;
70 fMipLevels = std::move(mipLevels);
71}
72
73///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips11c67672020-04-23 15:10:03 -040074PromiseImageCallbackContext::~PromiseImageCallbackContext() {
Brian Salomon96796122021-01-19 12:11:07 -050075 SkASSERT(fDoneCnt == fNumImages);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050076 SkASSERT(!fTotalFulfills || fDoneCnt);
Robert Phillips96601082018-05-29 16:13:26 -040077
Brian Salomon3f4cd772019-01-11 16:03:19 -050078 if (fPromiseImageTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040079 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
Robert Phillips96601082018-05-29 16:13:26 -040080 }
81}
82
Robert Phillips11c67672020-04-23 15:10:03 -040083void PromiseImageCallbackContext::setBackendTexture(const GrBackendTexture& backendTexture) {
Brian Salomon7d88f312019-02-28 10:03:03 -050084 SkASSERT(!fPromiseImageTexture);
Robert Phillips923181b2020-02-14 12:36:37 -050085 SkASSERT(fBackendFormat == backendTexture.getBackendFormat());
Kevin Lubickeb981252023-06-13 07:51:26 -040086 fPromiseImageTexture = GrPromiseImageTexture::Make(backendTexture);
Brian Salomoncdd8a0a2019-01-10 12:09:52 -050087}
88
Robert Phillipsd5f3c982020-07-07 13:18:47 -040089void PromiseImageCallbackContext::destroyBackendTexture() {
90 SkASSERT(!fPromiseImageTexture || fPromiseImageTexture->unique());
91
92 if (fPromiseImageTexture) {
93 fContext->deleteBackendTexture(fPromiseImageTexture->backendTexture());
94 }
95 fPromiseImageTexture = nullptr;
96}
97
Robert Phillips96601082018-05-29 16:13:26 -040098///////////////////////////////////////////////////////////////////////////////////////////////////
99
Robert Phillips0d8722c2021-03-29 13:29:40 -0400100sk_sp<SkPicture> DDLPromiseImageHelper::recreateSKP(GrDirectContext* dContext,
101 SkPicture* inputPicture) {
Robert Phillips96601082018-05-29 16:13:26 -0400102 SkSerialProcs procs;
103
104 procs.fImageCtx = this;
105 procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> {
106 auto helper = static_cast<DDLPromiseImageHelper*>(ctx);
107
108 int id = helper->findOrDefineImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400109
Robert Phillips6bad7052019-12-16 15:09:57 -0500110 // Even if 'id' is invalid (i.e., -1) write it to the SKP
111 return SkData::MakeWithCopy(&id, sizeof(id));
Robert Phillips96601082018-05-29 16:13:26 -0400112 };
113
Robert Phillips0d8722c2021-03-29 13:29:40 -0400114 sk_sp<SkData> compressedPictureData = inputPicture->serialize(&procs);
115 if (!compressedPictureData) {
116 return nullptr;
117 }
118
119 this->createCallbackContexts(dContext);
120
121 return this->reinflateSKP(dContext->threadSafeProxy(), compressedPictureData.get());
Robert Phillips96601082018-05-29 16:13:26 -0400122}
123
Brian Salomonbd3792d2020-11-10 14:17:58 -0500124static GrBackendTexture create_yuva_texture(GrDirectContext* direct,
125 const SkPixmap& pm,
126 int texIndex) {
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500127 SkASSERT(texIndex >= 0 && texIndex <= 3);
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400128
Greg Danielc1ad77c2020-05-06 11:40:03 -0400129 bool finishedBECreate = false;
130 auto markFinished = [](void* context) {
131 *(bool*)context = true;
132 };
Brian Salomonb5f880a2020-12-07 11:30:16 -0500133 auto beTex = direct->createBackendTexture(pm,
134 kTopLeft_GrSurfaceOrigin,
135 GrRenderable::kNo,
136 GrProtected::kNo,
137 markFinished,
Aditya Kushwah8acbc3c2022-08-24 09:31:11 -0700138 &finishedBECreate,
139 /*label=*/"CreateYuvaTexture");
Greg Danielc1ad77c2020-05-06 11:40:03 -0400140 if (beTex.isValid()) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400141 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400142 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400143 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400144 }
145 }
146 return beTex;
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500147}
148
Robert Phillips923181b2020-02-14 12:36:37 -0500149/*
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 */
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400154void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext* direct,
Robert Phillips923181b2020-02-14 12:36:37 -0500155 PromiseImageInfo* info) {
Robert Phillips923181b2020-02-14 12:36:37 -0500156 if (info->isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500157 int numPixmaps = info->yuvaInfo().numPlanes();
Robert Phillips923181b2020-02-14 12:36:37 -0500158 for (int j = 0; j < numPixmaps; ++j) {
159 const SkPixmap& yuvPixmap = info->yuvPixmap(j);
160
161 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
162 SkASSERT(callbackContext);
163
Robert Phillips4508eb92020-04-15 15:54:34 -0400164 // DDL TODO: what should we do with mipmapped YUV images
Brian Salomonbd3792d2020-11-10 14:17:58 -0500165 callbackContext->setBackendTexture(create_yuva_texture(direct, yuvPixmap, j));
Robert Phillips923181b2020-02-14 12:36:37 -0500166 SkASSERT(callbackContext->promiseImageTexture());
167 }
168 } else {
169 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
170 if (!callbackContext) {
171 // This texture would've been too large to fit on the GPU
172 return;
173 }
174
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400175 std::unique_ptr<SkPixmap[]> mipLevels = info->normalMipLevels();
Robert Phillips923181b2020-02-14 12:36:37 -0500176
Greg Danielc1ad77c2020-05-06 11:40:03 -0400177 bool finishedBECreate = false;
178 auto markFinished = [](void* context) {
179 *(bool*)context = true;
180 };
Brian Salomonb5f880a2020-12-07 11:30:16 -0500181 auto backendTex = direct->createBackendTexture(mipLevels.get(),
182 info->numMipLevels(),
183 kTopLeft_GrSurfaceOrigin,
184 GrRenderable::kNo,
185 GrProtected::kNo,
186 markFinished,
Aditya Kushwah8acbc3c2022-08-24 09:31:11 -0700187 &finishedBECreate,
188 /*label=*/"CreateBETexturesForPromiseImage");
Robert Phillips923181b2020-02-14 12:36:37 -0500189 SkASSERT(backendTex.isValid());
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400190 direct->submit();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400191 while (!finishedBECreate) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400192 direct->checkAsyncWorkCompletion();
Greg Danielc1ad77c2020-05-06 11:40:03 -0400193 }
Robert Phillips923181b2020-02-14 12:36:37 -0500194
195 callbackContext->setBackendTexture(backendTex);
196 }
197}
198
Brian Salomonbd3792d2020-11-10 14:17:58 -0500199void DDLPromiseImageHelper::DeleteBETexturesForPromiseImage(PromiseImageInfo* info) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500200 if (info->isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500201 int numPixmaps = info->yuvaInfo().numPlanes();
Robert Phillips19f466d2020-02-26 10:27:07 -0500202 for (int j = 0; j < numPixmaps; ++j) {
203 PromiseImageCallbackContext* callbackContext = info->callbackContext(j);
204 SkASSERT(callbackContext);
205
206 callbackContext->destroyBackendTexture();
207 SkASSERT(!callbackContext->promiseImageTexture());
208 }
209 } else {
210 PromiseImageCallbackContext* callbackContext = info->callbackContext(0);
211 if (!callbackContext) {
212 // This texture would've been too large to fit on the GPU
213 return;
214 }
215
216 callbackContext->destroyBackendTexture();
217 SkASSERT(!callbackContext->promiseImageTexture());
218 }
219}
220
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400221void DDLPromiseImageHelper::createCallbackContexts(GrDirectContext* direct) {
222 const GrCaps* caps = direct->priv().caps();
Robert Phillips923181b2020-02-14 12:36:37 -0500223 const int maxDimension = caps->maxTextureSize();
224
Herb Derbyffacce52022-11-09 10:51:34 -0500225 for (int i = 0; i < fImageInfo.size(); ++i) {
Robert Phillips923181b2020-02-14 12:36:37 -0500226 PromiseImageInfo& info = fImageInfo[i];
227
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400228 if (info.isYUV()) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500229 int numPixmaps = info.yuvaInfo().numPlanes();
Robert Phillips923181b2020-02-14 12:36:37 -0500230
Jim Van Verth8f11e432018-10-18 14:36:59 -0400231 for (int j = 0; j < numPixmaps; ++j) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400232 const SkPixmap& yuvPixmap = info.yuvPixmap(j);
Robert Phillips96601082018-05-29 16:13:26 -0400233
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400234 GrBackendFormat backendFormat = direct->defaultBackendFormat(yuvPixmap.colorType(),
235 GrRenderable::kNo);
Robert Phillips923181b2020-02-14 12:36:37 -0500236
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400237 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400238 new PromiseImageCallbackContext(direct, backendFormat));
Jim Van Verth60ac5d02018-12-06 13:11:53 -0500239
Robert Phillips923181b2020-02-14 12:36:37 -0500240 info.setCallbackContext(j, std::move(callbackContext));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400241 }
242 } else {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400243 const SkBitmap& baseLevel = info.baseLevel();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400244
Robert Phillips923181b2020-02-14 12:36:37 -0500245 // TODO: explicitly mark the PromiseImageInfo as too big and check in uploadAllToGPU
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400246 if (maxDimension < std::max(baseLevel.width(), baseLevel.height())) {
Robert Phillips923181b2020-02-14 12:36:37 -0500247 // This won't fit on the GPU. Fallback to a raster-backed image per tile.
248 continue;
249 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400250
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400251 GrBackendFormat backendFormat = direct->defaultBackendFormat(baseLevel.colorType(),
252 GrRenderable::kNo);
Greg Daniel0e9d34d2021-08-13 16:20:18 -0400253 if (!caps->isFormatTexturable(backendFormat, GrTextureType::k2D)) {
Robert Phillips923181b2020-02-14 12:36:37 -0500254 continue;
255 }
Robert Phillipscb1adb42019-06-10 15:09:34 -0400256
Robert Phillips923181b2020-02-14 12:36:37 -0500257 sk_sp<PromiseImageCallbackContext> callbackContext(
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400258 new PromiseImageCallbackContext(direct, backendFormat));
Robert Phillips923181b2020-02-14 12:36:37 -0500259
260 info.setCallbackContext(0, std::move(callbackContext));
261 }
262 }
263}
264
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400265void DDLPromiseImageHelper::uploadAllToGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips923181b2020-02-14 12:36:37 -0500266 if (taskGroup) {
Herb Derbyffacce52022-11-09 10:51:34 -0500267 for (int i = 0; i < fImageInfo.size(); ++i) {
Robert Phillips923181b2020-02-14 12:36:37 -0500268 PromiseImageInfo* info = &fImageInfo[i];
269
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400270 taskGroup->add([direct, info]() { CreateBETexturesForPromiseImage(direct, info); });
Robert Phillips923181b2020-02-14 12:36:37 -0500271 }
272 } else {
Herb Derbyffacce52022-11-09 10:51:34 -0500273 for (int i = 0; i < fImageInfo.size(); ++i) {
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400274 CreateBETexturesForPromiseImage(direct, &fImageInfo[i]);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400275 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500276 }
277}
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400278
Robert Phillipsd5f3c982020-07-07 13:18:47 -0400279void DDLPromiseImageHelper::deleteAllFromGPU(SkTaskGroup* taskGroup, GrDirectContext* direct) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500280 if (taskGroup) {
Herb Derbyffacce52022-11-09 10:51:34 -0500281 for (int i = 0; i < fImageInfo.size(); ++i) {
Robert Phillips19f466d2020-02-26 10:27:07 -0500282 PromiseImageInfo* info = &fImageInfo[i];
283
Brian Salomonbd3792d2020-11-10 14:17:58 -0500284 taskGroup->add([info]() { DeleteBETexturesForPromiseImage(info); });
Robert Phillips19f466d2020-02-26 10:27:07 -0500285 }
286 } else {
Herb Derbyffacce52022-11-09 10:51:34 -0500287 for (int i = 0; i < fImageInfo.size(); ++i) {
Brian Salomonbd3792d2020-11-10 14:17:58 -0500288 DeleteBETexturesForPromiseImage(&fImageInfo[i]);
Robert Phillips19f466d2020-02-26 10:27:07 -0500289 }
290 }
291}
292
Robert Phillips96601082018-05-29 16:13:26 -0400293sk_sp<SkPicture> DDLPromiseImageHelper::reinflateSKP(
Adlai Holler55aaefe2021-03-03 16:12:56 -0700294 sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
Robert Phillips0d8722c2021-03-29 13:29:40 -0400295 SkData* compressedPictureData) {
296 DeserialImageProcContext procContext { std::move(threadSafeProxy), this };
Robert Phillips96601082018-05-29 16:13:26 -0400297
298 SkDeserialProcs procs;
Adlai Holler55aaefe2021-03-03 16:12:56 -0700299 procs.fImageCtx = (void*) &procContext;
Robert Phillips923181b2020-02-14 12:36:37 -0500300 procs.fImageProc = CreatePromiseImages;
Robert Phillips96601082018-05-29 16:13:26 -0400301
302 return SkPicture::MakeFromData(compressedPictureData, &procs);
303}
304
Robert Phillips0d8722c2021-03-29 13:29:40 -0400305// This generates promise images to replace the indices in the compressed picture.
Robert Phillips923181b2020-02-14 12:36:37 -0500306sk_sp<SkImage> DDLPromiseImageHelper::CreatePromiseImages(const void* rawData,
Robert Phillips0d8722c2021-03-29 13:29:40 -0400307 size_t length,
308 void* ctxIn) {
Adlai Holler55aaefe2021-03-03 16:12:56 -0700309 DeserialImageProcContext* procContext = static_cast<DeserialImageProcContext*>(ctxIn);
Robert Phillips0d8722c2021-03-29 13:29:40 -0400310 DDLPromiseImageHelper* helper = procContext->fHelper;
Robert Phillips96601082018-05-29 16:13:26 -0400311
312 SkASSERT(length == sizeof(int));
313
314 const int* indexPtr = static_cast<const int*>(rawData);
Robert Phillips6bad7052019-12-16 15:09:57 -0500315 if (!helper->isValidID(*indexPtr)) {
316 return nullptr;
317 }
Robert Phillips96601082018-05-29 16:13:26 -0400318
319 const DDLPromiseImageHelper::PromiseImageInfo& curImage = helper->getInfo(*indexPtr);
320
Robert Phillips923181b2020-02-14 12:36:37 -0500321 // If there is no callback context that means 'createCallbackContexts' determined the
Robert Phillips0d8722c2021-03-29 13:29:40 -0400322 // texture wouldn't fit on the GPU. Create a bitmap-backed image.
Robert Phillips923181b2020-02-14 12:36:37 -0500323 if (!curImage.isYUV() && !curImage.callbackContext(0)) {
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400324 SkASSERT(curImage.baseLevel().isImmutable());
Mike Reeddc607e32020-12-23 11:50:36 -0500325 return curImage.baseLevel().asImage();
Robert Phillips96601082018-05-29 16:13:26 -0400326 }
Robert Phillips923181b2020-02-14 12:36:37 -0500327
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400328 SkASSERT(curImage.index() == *indexPtr);
Robert Phillips96601082018-05-29 16:13:26 -0400329
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400330 sk_sp<SkImage> image;
331 if (curImage.isYUV()) {
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500332 GrBackendFormat backendFormats[SkYUVAInfo::kMaxPlanes];
Brian Salomonbd3792d2020-11-10 14:17:58 -0500333 const SkYUVAInfo& yuvaInfo = curImage.yuvaInfo();
Brian Salomon0c0b5a62021-01-11 14:40:44 -0500334 void* contexts[SkYUVAInfo::kMaxPlanes] = {nullptr, nullptr, nullptr, nullptr};
Brian Salomonbd3792d2020-11-10 14:17:58 -0500335 int textureCount = yuvaInfo.numPlanes();
Jim Van Verth8f11e432018-10-18 14:36:59 -0400336 for (int i = 0; i < textureCount; ++i) {
Robert Phillips923181b2020-02-14 12:36:37 -0500337 backendFormats[i] = curImage.backendFormat(i);
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400338 contexts[i] = curImage.refCallbackContext(i).release();
339 }
Kevin Lubickdf73d162023-09-11 11:56:53 -0400340 GrYUVABackendTextureInfo yuvaBackendTextures(
341 yuvaInfo, backendFormats, skgpu::Mipmapped::kNo, kTopLeft_GrSurfaceOrigin);
Kevin Lubick77472bf2023-03-24 07:11:17 -0400342 image = SkImages::PromiseTextureFromYUVA(
343 procContext->fThreadSafeProxy,
344 yuvaBackendTextures,
345 curImage.refOverallColorSpace(),
346 PromiseImageCallbackContext::PromiseImageFulfillProc,
347 PromiseImageCallbackContext::PromiseImageReleaseProc,
348 contexts);
Brian Salomon72068172020-12-17 09:38:59 -0500349 if (!image) {
350 return nullptr;
351 }
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500352 for (int i = 0; i < textureCount; ++i) {
353 curImage.callbackContext(i)->wasAddedToImage();
354 }
Robert Phillips193c4212019-03-04 12:18:53 -0500355
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400356 } else {
John Stiles31954bf2020-08-07 17:35:54 -0400357 const GrBackendFormat& backendFormat = curImage.backendFormat(0);
Brian Salomonf391d0f2018-12-14 09:18:50 -0500358 SkASSERT(backendFormat.isValid());
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400359
Kevin Lubick77472bf2023-03-24 07:11:17 -0400360 image = SkImages::PromiseTextureFrom(procContext->fThreadSafeProxy,
361 backendFormat,
362 curImage.overallDimensions(),
363 curImage.mipmapped(0),
364 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
365 curImage.overallColorType(),
366 curImage.overallAlphaType(),
367 curImage.refOverallColorSpace(),
368 PromiseImageCallbackContext::PromiseImageFulfillProc,
369 PromiseImageCallbackContext::PromiseImageReleaseProc,
370 (void*)curImage.refCallbackContext(0).release());
Brian Salomoncdd8a0a2019-01-10 12:09:52 -0500371 curImage.callbackContext(0)->wasAddedToImage();
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400372 }
Robert Phillips0d8722c2021-03-29 13:29:40 -0400373 helper->fPromiseImages.push_back(image);
Robert Phillips96601082018-05-29 16:13:26 -0400374 SkASSERT(image);
375 return image;
376}
377
378int DDLPromiseImageHelper::findImage(SkImage* image) const {
Herb Derbyffacce52022-11-09 10:51:34 -0500379 for (int i = 0; i < fImageInfo.size(); ++i) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400380 if (fImageInfo[i].originalUniqueID() == image->uniqueID()) { // trying to dedup here
381 SkASSERT(fImageInfo[i].index() == i);
382 SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].index()));
Robert Phillips96601082018-05-29 16:13:26 -0400383 return i;
384 }
385 }
386 return -1;
387}
388
389int DDLPromiseImageHelper::addImage(SkImage* image) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400390 SkImage_Base* ib = as_IB(image);
Robert Phillips96601082018-05-29 16:13:26 -0400391
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400392 SkImageInfo overallII = SkImageInfo::Make(image->width(), image->height(),
Robert Phillips13371a12019-05-13 15:59:10 -0400393 image->colorType() == kBGRA_8888_SkColorType
394 ? kRGBA_8888_SkColorType
395 : image->colorType(),
396 image->alphaType(),
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400397 image->refColorSpace());
Robert Phillips96601082018-05-29 16:13:26 -0400398
Herb Derbyffacce52022-11-09 10:51:34 -0500399 PromiseImageInfo& newImageInfo = fImageInfo.emplace_back(fImageInfo.size(),
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400400 image->uniqueID(),
401 overallII);
Robert Phillips96601082018-05-29 16:13:26 -0400402
Brian Salomonefb5f072020-07-28 21:06:43 -0400403 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(ib->refEncodedData());
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400404 SkYUVAPixmapInfo yuvaInfo;
Brian Salomon59c60b02020-09-01 15:01:15 -0400405 if (codec && codec->queryYUVAInfo(fSupportedYUVADataTypes, &yuvaInfo)) {
Brian Salomonbe0e42c2020-08-27 11:00:04 -0400406 auto yuvaPixmaps = SkYUVAPixmaps::Allocate(yuvaInfo);
Robert Phillips9c2ab4c2021-02-02 10:01:59 -0500407 if (!codec->getYUVAPlanes(yuvaPixmaps)) {
408 return -1;
409 }
Brian Salomon5660e8b2020-08-25 12:40:32 -0400410 SkASSERT(yuvaPixmaps.isValid());
411 newImageInfo.setYUVPlanes(std::move(yuvaPixmaps));
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400412 } else {
413 sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
Robert Phillipse84bffc2019-12-16 11:22:17 -0500414 if (!rasterImage) {
415 return -1;
416 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400417
418 SkBitmap tmp;
419 tmp.allocPixels(overallII);
420
Adlai Hollerbcfc5542020-08-27 12:44:07 -0400421 if (!rasterImage->readPixels(nullptr, tmp.pixmap(), 0, 0)) {
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400422 return -1;
423 }
424
425 tmp.setImmutable();
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400426
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.
Mike Reed13711eb2020-07-14 17:16:32 -0400431 std::unique_ptr<SkMipmap> mipmaps(SkMipmap::Build(tmp.pixmap(), nullptr));
Robert Phillipsf95e2f42020-04-17 16:20:55 -0400432
433 newImageInfo.setMipLevels(tmp, std::move(mipmaps));
Robert Phillips96601082018-05-29 16:13:26 -0400434 }
Robert Phillipse8e2bb12018-09-27 14:26:47 -0400435 // In either case newImageInfo's PromiseImageCallbackContext is filled in by uploadAllToGPU
Robert Phillips96601082018-05-29 16:13:26 -0400436
Herb Derbyffacce52022-11-09 10:51:34 -0500437 return fImageInfo.size()-1;
Robert Phillips96601082018-05-29 16:13:26 -0400438}
439
440int DDLPromiseImageHelper::findOrDefineImage(SkImage* image) {
441 int preExistingID = this->findImage(image);
442 if (preExistingID >= 0) {
443 SkASSERT(this->isValidID(preExistingID));
444 return preExistingID;
445 }
446
447 int newID = this->addImage(image);
Robert Phillips96601082018-05-29 16:13:26 -0400448 return newID;
449}