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