Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkImage_Lazy.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 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
9
12#include "include/core/SkData.h"
15#include "include/core/SkSize.h"
19#include "src/core/SkNextID.h"
22
23#include <utility>
24
25enum SkColorType : int;
26
27sk_sp<SharedGenerator> SharedGenerator::Make(std::unique_ptr<SkImageGenerator> gen) {
28 return gen ? sk_sp<SharedGenerator>(new SharedGenerator(std::move(gen))) : nullptr;
29}
30
31SharedGenerator::SharedGenerator(std::unique_ptr<SkImageGenerator> gen)
32 : fGenerator(std::move(gen)) {
34}
35
36const SkImageInfo& SharedGenerator::getInfo() const { return fGenerator->getInfo(); }
37
38bool SharedGenerator::isTextureGenerator() { return fGenerator->isTextureGenerator(); }
39
40///////////////////////////////////////////////////////////////////////////////
41
43 sk_sp<SkColorSpace> colorSpace)
44 : fSharedGenerator(std::move(gen)) {
45 if (!fSharedGenerator) {
46 return;
47 }
48
49 // The following generator accessors are safe without acquiring the mutex (const getters).
50 // TODO: refactor to use a ScopedGenerator instead, for clarity.
51 fInfo = fSharedGenerator->fGenerator->getInfo();
52 if (fInfo.isEmpty()) {
54 return;
55 }
56
58
59 if (colorType && (*colorType == fInfo.colorType())) {
60 colorType = nullptr;
61 }
62
63 if (colorType || colorSpace) {
64 if (colorType) {
66 }
67 if (colorSpace) {
69 }
71 }
72}
73
74///////////////////////////////////////////////////////////////////////////////
75
76// Helper for exclusive access to a shared generator.
78public:
80 : fSharedGenerator(gen)
81 , fAutoAcquire(gen->fMutex) {}
82
84 fSharedGenerator->fMutex.assertHeld();
85 return fSharedGenerator->fGenerator.get();
86 }
87
88 operator SkImageGenerator*() const {
89 fSharedGenerator->fMutex.assertHeld();
90 return fSharedGenerator->fGenerator.get();
91 }
92
93private:
94 const sk_sp<SharedGenerator>& fSharedGenerator;
95 SkAutoMutexExclusive fAutoAcquire;
96};
97
98///////////////////////////////////////////////////////////////////////////////
99
101 : SkImage_Base(validator->fInfo, validator->fUniqueID)
102 , fSharedGenerator(std::move(validator->fSharedGenerator))
103{
104 SkASSERT(fSharedGenerator);
105}
106
108 SkImage::CachingHint chint) const {
109 auto check_output_bitmap = [bitmap]() {
110 SkASSERT(bitmap->isImmutable());
111 SkASSERT(bitmap->getPixels());
112 (void)bitmap;
113 };
114
115 auto desc = SkBitmapCacheDesc::Make(this);
116 if (SkBitmapCache::Find(desc, bitmap)) {
117 check_output_bitmap();
118 return true;
119 }
120
121 if (SkImage::kAllow_CachingHint == chint) {
122 SkPixmap pmap;
123 SkBitmapCache::RecPtr cacheRec = SkBitmapCache::Alloc(desc, this->imageInfo(), &pmap);
124 if (!cacheRec) {
125 return false;
126 }
127 bool success = false;
128 { // make sure ScopedGenerator goes out of scope before we try readPixelsProxy
129 success = ScopedGenerator(fSharedGenerator)->getPixels(pmap);
130 }
131 if (!success && !this->readPixelsProxy(ctx, pmap)) {
132 return false;
133 }
134 SkBitmapCache::Add(std::move(cacheRec), bitmap);
136 } else {
137 if (!bitmap->tryAllocPixels(this->imageInfo())) {
138 return false;
139 }
140 bool success = false;
141 { // make sure ScopedGenerator goes out of scope before we try readPixelsProxy
142 success = ScopedGenerator(fSharedGenerator)->getPixels(bitmap->pixmap());
143 }
144 if (!success && !this->readPixelsProxy(ctx, bitmap->pixmap())) {
145 return false;
146 }
147 bitmap->setImmutable();
148 }
149 check_output_bitmap();
150 return true;
151}
152
154 return fSharedGenerator;
155}
156
158 ScopedGenerator generator(fSharedGenerator);
159 return generator->isProtected();
160}
161
163 const SkImageInfo& dstInfo,
164 void* dstPixels,
165 size_t dstRB,
166 int srcX,
167 int srcY,
168 CachingHint chint) const {
169 SkBitmap bm;
170 if (this->getROPixels(dContext, &bm, chint)) {
171 return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
172 }
173 return false;
174}
175
177 // check that we aren't a subset or colortype/etc modification of the original
178 if (fSharedGenerator->fGenerator->uniqueID() == this->uniqueID()) {
179 ScopedGenerator generator(fSharedGenerator);
180 return generator->refEncodedData();
181 }
182 return nullptr;
183}
184
186 ScopedGenerator generator(fSharedGenerator);
187 return generator->isValid(context);
188}
189
190
192 // neither picture-backed nor codec-backed lazy images need the context to do readbacks.
193 // The subclass for cross-context images *does* use the direct context.
194 auto pixels = this->makeRasterImage(nullptr);
195 return pixels ? pixels->makeSubset(nullptr, subset) : nullptr;
196}
197
199 const SkIRect& subset,
200 RequiredProperties props) const {
201 // TODO: can we do this more efficiently, by telling the generator we want to
202 // "realize" a subset?
203 sk_sp<SkImage> nonLazyImg = this->makeRasterImage(nullptr);
204 if (!nonLazyImg) {
205 return nullptr;
206 }
207 return nonLazyImg->makeSubset(nullptr, subset, props);
208}
209
211 sk_sp<SkColorSpace> targetCS,
212 GrDirectContext*) const {
213 SkAutoMutexExclusive autoAquire(fOnMakeColorTypeAndSpaceMutex);
214 if (fOnMakeColorTypeAndSpaceResult &&
215 targetCT == fOnMakeColorTypeAndSpaceResult->colorType() &&
216 SkColorSpace::Equals(targetCS.get(), fOnMakeColorTypeAndSpaceResult->colorSpace())) {
217 return fOnMakeColorTypeAndSpaceResult;
218 }
219 Validator validator(fSharedGenerator, &targetCT, targetCS);
220 sk_sp<SkImage> result = validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr;
221 if (result) {
222 fOnMakeColorTypeAndSpaceResult = result;
223 }
224 return result;
225}
226
228 // TODO: The correct thing is to clone the generator, and modify its color space. That's hard,
229 // because we don't have a clone method, and generator is public (and derived-from by clients).
230 // So do the simple/inefficient thing here, and fallback to raster when this is called.
231
232 // We allocate the bitmap with the new color space, then generate the image using the original.
234 if (bitmap.tryAllocPixels(this->imageInfo().makeColorSpace(std::move(newCS)))) {
235 SkPixmap pixmap = bitmap.pixmap();
236 pixmap.setColorSpace(this->refColorSpace());
237 if (ScopedGenerator(fSharedGenerator)->getPixels(pixmap)) {
238 bitmap.setImmutable();
239 return bitmap.asImage();
240 }
241 }
242 return nullptr;
243}
244
246 const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
247 SkYUVAPixmaps* yuvaPixmaps) const {
248 ScopedGenerator generator(fSharedGenerator);
249
250 sk_sp<SkCachedData> data(SkYUVPlanesCache::FindAndRef(generator->uniqueID(), yuvaPixmaps));
251
252 if (data) {
253 SkASSERT(yuvaPixmaps->isValid());
254 SkASSERT(yuvaPixmaps->yuvaInfo().dimensions() == this->dimensions());
255 return data;
256 }
257 SkYUVAPixmapInfo yuvaPixmapInfo;
258 if (!generator->queryYUVAInfo(supportedDataTypes, &yuvaPixmapInfo) ||
259 yuvaPixmapInfo.yuvaInfo().dimensions() != this->dimensions()) {
260 return nullptr;
261 }
262 data.reset(SkResourceCache::NewCachedData(yuvaPixmapInfo.computeTotalBytes()));
263 SkYUVAPixmaps tempPixmaps = SkYUVAPixmaps::FromExternalMemory(yuvaPixmapInfo,
264 data->writable_data());
265 SkASSERT(tempPixmaps.isValid());
266 if (!generator->getYUVAPlanes(tempPixmaps)) {
267 return nullptr;
268 }
269 // Decoding is done, cache the resulting YUV planes
270 *yuvaPixmaps = tempPixmaps;
271 SkYUVPlanesCache::Add(this->uniqueID(), data.get(), *yuvaPixmaps);
272 return data;
273}
274
276 fUniqueIDListeners.add(std::move(listener));
277}
278
279// TODO(kjlubick) move SharedGenerate to SkImage_Lazy.h and this to SkImage_LazyFactories
280namespace SkImages {
281
282sk_sp<SkImage> DeferredFromGenerator(std::unique_ptr<SkImageGenerator> generator) {
283 SkImage_Lazy::Validator validator(
284 SharedGenerator::Make(std::move(generator)), nullptr, nullptr);
285
286 return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr;
287}
288
289} // namespace SkImages
#define SkASSERT(cond)
Definition SkAssert.h:116
SkColorType
Definition SkColorType.h:19
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
Type::kYUV Type::kRGBA() int(0.7 *637)
static sk_sp< SharedGenerator > Make(std::unique_ptr< SkImageGenerator > gen)
const SkImageInfo & getInfo() const
std::unique_ptr< SkImageGenerator > fGenerator
bool isTextureGenerator()
std::unique_ptr< Rec, RecDeleter > RecPtr
static RecPtr Alloc(const SkBitmapCacheDesc &, const SkImageInfo &, SkPixmap *)
static bool Find(const SkBitmapCacheDesc &, SkBitmap *result)
static void Add(RecPtr, SkBitmap *)
bool readPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY) const
Definition SkBitmap.cpp:488
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
Definition SkBitmap.cpp:271
static bool Equals(const SkColorSpace *, const SkColorSpace *)
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)
bool getPixels(const SkImageInfo &info, void *pixels, size_t rowBytes)
virtual GrImageContext * context() const
virtual void notifyAddedToRasterCache() const
SkImageGenerator * operator->() const
ScopedGenerator(const sk_sp< SharedGenerator > &gen)
SkImage_Lazy(Validator *validator)
virtual bool readPixelsProxy(GrDirectContext *, const SkPixmap &) const
bool getROPixels(GrDirectContext *, SkBitmap *, CachingHint) const override
void addUniqueIDListener(sk_sp< SkIDChangeListener >) const
sk_sp< SharedGenerator > generator() const
bool onIsProtected() const override
sk_sp< SkImage > onReinterpretColorSpace(sk_sp< SkColorSpace >) const final
bool isValid(GrRecordingContext *) const override
bool onReadPixels(GrDirectContext *, const SkImageInfo &, void *, size_t, int srcX, int srcY, CachingHint) const override
sk_sp< SkImage > onMakeSubset(GrDirectContext *, const SkIRect &) const override
sk_sp< SkData > onRefEncoded() const override
sk_sp< SkImage > onMakeColorTypeAndColorSpace(SkColorType, sk_sp< SkColorSpace >, GrDirectContext *) const override
sk_sp< SkCachedData > getPlanes(const SkYUVAPixmapInfo::SupportedDataTypes &supportedDataTypes, SkYUVAPixmaps *pixmaps) const
sk_sp< SkImage > makeRasterImage(GrDirectContext *, CachingHint cachingHint=kDisallow_CachingHint) const
Definition SkImage.cpp:267
const SkImageInfo & imageInfo() const
Definition SkImage.h:279
SkColorSpace * colorSpace() const
Definition SkImage.cpp:156
uint32_t uniqueID() const
Definition SkImage.h:311
SkColorType colorType() const
Definition SkImage.cpp:152
CachingHint
Definition SkImage.h:463
@ kAllow_CachingHint
allows internally caching decoded and copied pixels
Definition SkImage.h:464
sk_sp< SkColorSpace > refColorSpace() const
Definition SkImage.cpp:158
static uint32_t ImageID()
void setColorSpace(sk_sp< SkColorSpace > colorSpace)
Definition SkPixmap.cpp:57
static SkCachedData * NewCachedData(size_t bytes)
SkISize dimensions() const
Definition SkYUVAInfo.h:171
const SkYUVAInfo & yuvaInfo() const
size_t computeTotalBytes(size_t planeSizes[kMaxPlanes]=nullptr) const
const SkYUVAInfo & yuvaInfo() const
static SkYUVAPixmaps FromExternalMemory(const SkYUVAPixmapInfo &, void *memory)
bool isValid() const
static void Add(uint32_t genID, SkCachedData *data, const SkYUVAPixmaps &pixmaps, SkResourceCache *localCache=nullptr)
static SkCachedData * FindAndRef(uint32_t genID, SkYUVAPixmaps *pixmaps, SkResourceCache *localCache=nullptr)
T * get() const
Definition SkRefCnt.h:303
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
GAsyncResult * result
SK_API sk_sp< SkImage > DeferredFromGenerator(std::unique_ptr< SkImageGenerator > imageGenerator)
Definition gen.py:1
Definition ref_ptr.h:256
static SkBitmapCacheDesc Make(const SkImage *)
bool isEmpty() const
SkImageInfo makeColorSpace(sk_sp< SkColorSpace > cs) const
SkColorType colorType() const
SkImageInfo makeColorType(SkColorType newColorType) const
sk_sp< SharedGenerator > fSharedGenerator
Validator(sk_sp< SharedGenerator >, const SkColorType *, sk_sp< SkColorSpace >)