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