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