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#ifndef PromiseImageHelper_DEFINED 9cb93a386Sopenharmony_ci#define PromiseImageHelper_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 12cb93a386Sopenharmony_ci#include "include/core/SkDeferredDisplayListRecorder.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPromiseImageTexture.h" 14cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 15cb93a386Sopenharmony_ci#include "include/core/SkYUVAPixmaps.h" 16cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h" 17cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 18cb93a386Sopenharmony_ci#include "src/core/SkCachedData.h" 19cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciclass GrDirectContext; 22cb93a386Sopenharmony_ciclass SkImage; 23cb93a386Sopenharmony_ciclass SkMipmap; 24cb93a386Sopenharmony_ciclass SkPicture; 25cb93a386Sopenharmony_ciclass SkTaskGroup; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci// This class acts as a proxy for a GrBackendTexture that backs an image. 28cb93a386Sopenharmony_ci// Whenever a promise image is created for the image, the promise image receives a ref to 29cb93a386Sopenharmony_ci// potentially several of these objects. Once all the promise images receive their done 30cb93a386Sopenharmony_ci// callbacks this object is deleted - removing the GrBackendTexture from VRAM. 31cb93a386Sopenharmony_ci// Note that while the DDLs are being created in the threads, the PromiseImageHelper holds 32cb93a386Sopenharmony_ci// a ref on all the PromiseImageCallbackContexts. However, once all the threads are done 33cb93a386Sopenharmony_ci// it drops all of its refs (via "reset"). 34cb93a386Sopenharmony_ciclass PromiseImageCallbackContext : public SkRefCnt { 35cb93a386Sopenharmony_cipublic: 36cb93a386Sopenharmony_ci PromiseImageCallbackContext(GrDirectContext* direct, GrBackendFormat backendFormat) 37cb93a386Sopenharmony_ci : fContext(direct) 38cb93a386Sopenharmony_ci , fBackendFormat(backendFormat) {} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci ~PromiseImageCallbackContext() override; 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci const GrBackendFormat& backendFormat() const { return fBackendFormat; } 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci void setBackendTexture(const GrBackendTexture& backendTexture); 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci void destroyBackendTexture(); 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci sk_sp<SkPromiseImageTexture> fulfill() { 49cb93a386Sopenharmony_ci ++fTotalFulfills; 50cb93a386Sopenharmony_ci return fPromiseImageTexture; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci void release() { 54cb93a386Sopenharmony_ci ++fDoneCnt; 55cb93a386Sopenharmony_ci SkASSERT(fDoneCnt <= fNumImages); 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci void wasAddedToImage() { fNumImages++; } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci const SkPromiseImageTexture* promiseImageTexture() const { 61cb93a386Sopenharmony_ci return fPromiseImageTexture.get(); 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci static sk_sp<SkPromiseImageTexture> PromiseImageFulfillProc(void* textureContext) { 65cb93a386Sopenharmony_ci auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext); 66cb93a386Sopenharmony_ci return callbackContext->fulfill(); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci static void PromiseImageReleaseProc(void* textureContext) { 70cb93a386Sopenharmony_ci auto callbackContext = static_cast<PromiseImageCallbackContext*>(textureContext); 71cb93a386Sopenharmony_ci callbackContext->release(); 72cb93a386Sopenharmony_ci callbackContext->unref(); 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ciprivate: 76cb93a386Sopenharmony_ci GrDirectContext* fContext; 77cb93a386Sopenharmony_ci GrBackendFormat fBackendFormat; 78cb93a386Sopenharmony_ci sk_sp<SkPromiseImageTexture> fPromiseImageTexture; 79cb93a386Sopenharmony_ci int fNumImages = 0; 80cb93a386Sopenharmony_ci int fTotalFulfills = 0; 81cb93a386Sopenharmony_ci int fDoneCnt = 0; 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci using INHERITED = SkRefCnt; 84cb93a386Sopenharmony_ci}; 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci// This class consolidates tracking & extraction of the original image data from an skp, 87cb93a386Sopenharmony_ci// the upload of said data to the GPU and the fulfillment of promise images. 88cb93a386Sopenharmony_ci// 89cb93a386Sopenharmony_ci// The way this works is: 90cb93a386Sopenharmony_ci// the original skp is converted to SkData and all its image info is extracted into this 91cb93a386Sopenharmony_ci// class and only indices into this class are left in the SkData 92cb93a386Sopenharmony_ci// the PromiseImageCallbackContexts are created for each image 93cb93a386Sopenharmony_ci// the SkData is then reinflated into an SkPicture with promise images replacing all the indices 94cb93a386Sopenharmony_ci// (all in recreateSKP) 95cb93a386Sopenharmony_ci// 96cb93a386Sopenharmony_ci// Prior to replaying in threads, all the images are uploaded to the gpu 97cb93a386Sopenharmony_ci// (in uploadAllToGPU) 98cb93a386Sopenharmony_ci// 99cb93a386Sopenharmony_ci// This class is then reset - dropping all of its refs on the PromiseImageCallbackContexts 100cb93a386Sopenharmony_ci// 101cb93a386Sopenharmony_ci// Each done callback unrefs its PromiseImageCallbackContext so, once all the promise images 102cb93a386Sopenharmony_ci// are done, the PromiseImageCallbackContext is freed and its GrBackendTexture removed 103cb93a386Sopenharmony_ci// from VRAM 104cb93a386Sopenharmony_ci// 105cb93a386Sopenharmony_ci// Note: if DDLs are going to be replayed multiple times, the reset call can be delayed until 106cb93a386Sopenharmony_ci// all the replaying is complete. This will pin the GrBackendTextures in VRAM. 107cb93a386Sopenharmony_ciclass DDLPromiseImageHelper { 108cb93a386Sopenharmony_cipublic: 109cb93a386Sopenharmony_ci DDLPromiseImageHelper(const SkYUVAPixmapInfo::SupportedDataTypes& supportedYUVADataTypes) 110cb93a386Sopenharmony_ci : fSupportedYUVADataTypes(supportedYUVADataTypes) {} 111cb93a386Sopenharmony_ci ~DDLPromiseImageHelper() = default; 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci // Convert the input SkPicture into a new one which has promise images rather than live 114cb93a386Sopenharmony_ci // images. 115cb93a386Sopenharmony_ci sk_sp<SkPicture> recreateSKP(GrDirectContext*, SkPicture*); 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci void uploadAllToGPU(SkTaskGroup*, GrDirectContext*); 118cb93a386Sopenharmony_ci void deleteAllFromGPU(SkTaskGroup*, GrDirectContext*); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci // Remove this class' refs on the promise images and the PromiseImageCallbackContexts 121cb93a386Sopenharmony_ci void reset() { 122cb93a386Sopenharmony_ci fImageInfo.reset(); 123cb93a386Sopenharmony_ci fPromiseImages.reset(); 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ciprivate: 127cb93a386Sopenharmony_ci void createCallbackContexts(GrDirectContext*); 128cb93a386Sopenharmony_ci // reinflate a deflated SKP, replacing all the indices with promise images. 129cb93a386Sopenharmony_ci sk_sp<SkPicture> reinflateSKP(sk_sp<GrContextThreadSafeProxy>, SkData* deflatedSKP); 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci // This is the information extracted into this class from the parsing of the skp file. 132cb93a386Sopenharmony_ci // Once it has all been uploaded to the GPU and distributed to the promise images, it 133cb93a386Sopenharmony_ci // is all dropped via "reset". 134cb93a386Sopenharmony_ci class PromiseImageInfo { 135cb93a386Sopenharmony_ci public: 136cb93a386Sopenharmony_ci PromiseImageInfo(int index, uint32_t originalUniqueID, const SkImageInfo& ii); 137cb93a386Sopenharmony_ci PromiseImageInfo(PromiseImageInfo&& other); 138cb93a386Sopenharmony_ci ~PromiseImageInfo(); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci int index() const { return fIndex; } 141cb93a386Sopenharmony_ci uint32_t originalUniqueID() const { return fOriginalUniqueID; } 142cb93a386Sopenharmony_ci bool isYUV() const { return fYUVAPixmaps.isValid(); } 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci SkISize overallDimensions() const { return fImageInfo.dimensions(); } 145cb93a386Sopenharmony_ci SkColorType overallColorType() const { return fImageInfo.colorType(); } 146cb93a386Sopenharmony_ci SkAlphaType overallAlphaType() const { return fImageInfo.alphaType(); } 147cb93a386Sopenharmony_ci sk_sp<SkColorSpace> refOverallColorSpace() const { return fImageInfo.refColorSpace(); } 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci const SkYUVAInfo& yuvaInfo() const { return fYUVAPixmaps.yuvaInfo(); } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci const SkPixmap& yuvPixmap(int index) const { 152cb93a386Sopenharmony_ci SkASSERT(this->isYUV()); 153cb93a386Sopenharmony_ci return fYUVAPixmaps.planes()[index]; 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci const SkBitmap& baseLevel() const { 157cb93a386Sopenharmony_ci SkASSERT(!this->isYUV()); 158cb93a386Sopenharmony_ci return fBaseLevel; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci // This returns an array of all the available mipLevels - suitable for passing into 161cb93a386Sopenharmony_ci // createBackendTexture. 162cb93a386Sopenharmony_ci std::unique_ptr<SkPixmap[]> normalMipLevels() const; 163cb93a386Sopenharmony_ci int numMipLevels() const; 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci void setCallbackContext(int index, sk_sp<PromiseImageCallbackContext> callbackContext) { 166cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1)); 167cb93a386Sopenharmony_ci fCallbackContexts[index] = callbackContext; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci PromiseImageCallbackContext* callbackContext(int index) const { 170cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1)); 171cb93a386Sopenharmony_ci return fCallbackContexts[index].get(); 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci sk_sp<PromiseImageCallbackContext> refCallbackContext(int index) const { 174cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1)); 175cb93a386Sopenharmony_ci return fCallbackContexts[index]; 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci GrMipmapped mipMapped(int index) const { 179cb93a386Sopenharmony_ci if (this->isYUV()) { 180cb93a386Sopenharmony_ci return GrMipmapped::kNo; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci return fMipLevels ? GrMipmapped::kYes : GrMipmapped::kNo; 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci const GrBackendFormat& backendFormat(int index) const { 185cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1)); 186cb93a386Sopenharmony_ci return fCallbackContexts[index]->backendFormat(); 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci const SkPromiseImageTexture* promiseTexture(int index) const { 189cb93a386Sopenharmony_ci SkASSERT(index >= 0 && index < (this->isYUV() ? SkYUVAInfo::kMaxPlanes : 1)); 190cb93a386Sopenharmony_ci return fCallbackContexts[index]->promiseImageTexture(); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci void setMipLevels(const SkBitmap& baseLevel, std::unique_ptr<SkMipmap> mipLevels); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci /** Takes ownership of the plane data. */ 196cb93a386Sopenharmony_ci void setYUVPlanes(SkYUVAPixmaps yuvaPixmaps) { fYUVAPixmaps = std::move(yuvaPixmaps); } 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci private: 199cb93a386Sopenharmony_ci const int fIndex; // index in the 'fImageInfo' array 200cb93a386Sopenharmony_ci const uint32_t fOriginalUniqueID; // original ID for deduping 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci const SkImageInfo fImageInfo; // info for the overarching image 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci // CPU-side cache of a normal SkImage's mipmap levels 205cb93a386Sopenharmony_ci SkBitmap fBaseLevel; 206cb93a386Sopenharmony_ci std::unique_ptr<SkMipmap> fMipLevels; 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci // CPU-side cache of a YUV SkImage's contents 209cb93a386Sopenharmony_ci SkYUVAPixmaps fYUVAPixmaps; 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci // Up to SkYUVASizeInfo::kMaxCount for a YUVA image. Only one for a normal image. 212cb93a386Sopenharmony_ci sk_sp<PromiseImageCallbackContext> fCallbackContexts[SkYUVAInfo::kMaxPlanes]; 213cb93a386Sopenharmony_ci }; 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci struct DeserialImageProcContext { 216cb93a386Sopenharmony_ci sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy; 217cb93a386Sopenharmony_ci DDLPromiseImageHelper* fHelper; 218cb93a386Sopenharmony_ci }; 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci static void CreateBETexturesForPromiseImage(GrDirectContext*, PromiseImageInfo*); 221cb93a386Sopenharmony_ci static void DeleteBETexturesForPromiseImage(PromiseImageInfo*); 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci static sk_sp<SkImage> CreatePromiseImages(const void* rawData, size_t length, void* ctxIn); 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci bool isValidID(int id) const { return id >= 0 && id < fImageInfo.count(); } 226cb93a386Sopenharmony_ci const PromiseImageInfo& getInfo(int id) const { return fImageInfo[id]; } 227cb93a386Sopenharmony_ci void uploadImage(GrDirectContext*, PromiseImageInfo*); 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ci // returns -1 if not found 230cb93a386Sopenharmony_ci int findImage(SkImage* image) const; 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci // returns -1 on failure 233cb93a386Sopenharmony_ci int addImage(SkImage* image); 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci // returns -1 on failure 236cb93a386Sopenharmony_ci int findOrDefineImage(SkImage* image); 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci SkYUVAPixmapInfo::SupportedDataTypes fSupportedYUVADataTypes; 239cb93a386Sopenharmony_ci SkTArray<PromiseImageInfo> fImageInfo; 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci // TODO: review the use of 'fPromiseImages' - it doesn't seem useful/necessary 242cb93a386Sopenharmony_ci SkTArray<sk_sp<SkImage>> fPromiseImages; // All the promise images in the 243cb93a386Sopenharmony_ci // reconstituted picture 244cb93a386Sopenharmony_ci}; 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci#endif 247