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