xref: /aosp_15_r20/external/skia/src/image/SkImage_Lazy.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Lazy.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageGenerator.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAInfo.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBitmapCache.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCachedData.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkNextID.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkResourceCache.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkYUVPlanesCache.h"
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker class SkSurfaceProps;
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker enum SkColorType : int;
29*c8dee2aaSAndroid Build Coastguard Worker 
Make(std::unique_ptr<SkImageGenerator> gen)30*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SharedGenerator> SharedGenerator::Make(std::unique_ptr<SkImageGenerator> gen) {
31*c8dee2aaSAndroid Build Coastguard Worker     return gen ? sk_sp<SharedGenerator>(new SharedGenerator(std::move(gen))) : nullptr;
32*c8dee2aaSAndroid Build Coastguard Worker }
33*c8dee2aaSAndroid Build Coastguard Worker 
SharedGenerator(std::unique_ptr<SkImageGenerator> gen)34*c8dee2aaSAndroid Build Coastguard Worker SharedGenerator::SharedGenerator(std::unique_ptr<SkImageGenerator> gen)
35*c8dee2aaSAndroid Build Coastguard Worker         : fGenerator(std::move(gen)) {
36*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fGenerator);
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker 
getInfo() const39*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& SharedGenerator::getInfo() const { return fGenerator->getInfo(); }
40*c8dee2aaSAndroid Build Coastguard Worker 
isTextureGenerator()41*c8dee2aaSAndroid Build Coastguard Worker bool SharedGenerator::isTextureGenerator() { return fGenerator->isTextureGenerator(); }
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
44*c8dee2aaSAndroid Build Coastguard Worker 
Validator(sk_sp<SharedGenerator> gen,const SkColorType * colorType,sk_sp<SkColorSpace> colorSpace)45*c8dee2aaSAndroid Build Coastguard Worker SkImage_Lazy::Validator::Validator(sk_sp<SharedGenerator> gen, const SkColorType* colorType,
46*c8dee2aaSAndroid Build Coastguard Worker                                    sk_sp<SkColorSpace> colorSpace)
47*c8dee2aaSAndroid Build Coastguard Worker         : fSharedGenerator(std::move(gen)) {
48*c8dee2aaSAndroid Build Coastguard Worker     if (!fSharedGenerator) {
49*c8dee2aaSAndroid Build Coastguard Worker         return;
50*c8dee2aaSAndroid Build Coastguard Worker     }
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     // The following generator accessors are safe without acquiring the mutex (const getters).
53*c8dee2aaSAndroid Build Coastguard Worker     // TODO: refactor to use a ScopedGenerator instead, for clarity.
54*c8dee2aaSAndroid Build Coastguard Worker     fInfo = fSharedGenerator->fGenerator->getInfo();
55*c8dee2aaSAndroid Build Coastguard Worker     if (fInfo.isEmpty()) {
56*c8dee2aaSAndroid Build Coastguard Worker         fSharedGenerator.reset();
57*c8dee2aaSAndroid Build Coastguard Worker         return;
58*c8dee2aaSAndroid Build Coastguard Worker     }
59*c8dee2aaSAndroid Build Coastguard Worker 
60*c8dee2aaSAndroid Build Coastguard Worker     fUniqueID = fSharedGenerator->fGenerator->uniqueID();
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker     if (colorType && (*colorType == fInfo.colorType())) {
63*c8dee2aaSAndroid Build Coastguard Worker         colorType = nullptr;
64*c8dee2aaSAndroid Build Coastguard Worker     }
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     if (colorType || colorSpace) {
67*c8dee2aaSAndroid Build Coastguard Worker         if (colorType) {
68*c8dee2aaSAndroid Build Coastguard Worker             fInfo = fInfo.makeColorType(*colorType);
69*c8dee2aaSAndroid Build Coastguard Worker         }
70*c8dee2aaSAndroid Build Coastguard Worker         if (colorSpace) {
71*c8dee2aaSAndroid Build Coastguard Worker             fInfo = fInfo.makeColorSpace(colorSpace);
72*c8dee2aaSAndroid Build Coastguard Worker         }
73*c8dee2aaSAndroid Build Coastguard Worker         fUniqueID = SkNextID::ImageID();
74*c8dee2aaSAndroid Build Coastguard Worker     }
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker // Helper for exclusive access to a shared generator.
80*c8dee2aaSAndroid Build Coastguard Worker class SkImage_Lazy::ScopedGenerator {
81*c8dee2aaSAndroid Build Coastguard Worker public:
ScopedGenerator(const sk_sp<SharedGenerator> & gen)82*c8dee2aaSAndroid Build Coastguard Worker     ScopedGenerator(const sk_sp<SharedGenerator>& gen)
83*c8dee2aaSAndroid Build Coastguard Worker       : fSharedGenerator(gen)
84*c8dee2aaSAndroid Build Coastguard Worker       , fAutoAcquire(gen->fMutex) {}
85*c8dee2aaSAndroid Build Coastguard Worker 
operator ->() const86*c8dee2aaSAndroid Build Coastguard Worker     SkImageGenerator* operator->() const {
87*c8dee2aaSAndroid Build Coastguard Worker         fSharedGenerator->fMutex.assertHeld();
88*c8dee2aaSAndroid Build Coastguard Worker         return fSharedGenerator->fGenerator.get();
89*c8dee2aaSAndroid Build Coastguard Worker     }
90*c8dee2aaSAndroid Build Coastguard Worker 
operator SkImageGenerator*() const91*c8dee2aaSAndroid Build Coastguard Worker     operator SkImageGenerator*() const {
92*c8dee2aaSAndroid Build Coastguard Worker         fSharedGenerator->fMutex.assertHeld();
93*c8dee2aaSAndroid Build Coastguard Worker         return fSharedGenerator->fGenerator.get();
94*c8dee2aaSAndroid Build Coastguard Worker     }
95*c8dee2aaSAndroid Build Coastguard Worker 
96*c8dee2aaSAndroid Build Coastguard Worker private:
97*c8dee2aaSAndroid Build Coastguard Worker     const sk_sp<SharedGenerator>& fSharedGenerator;
98*c8dee2aaSAndroid Build Coastguard Worker     SkAutoMutexExclusive          fAutoAcquire;
99*c8dee2aaSAndroid Build Coastguard Worker };
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
102*c8dee2aaSAndroid Build Coastguard Worker 
SkImage_Lazy(Validator * validator)103*c8dee2aaSAndroid Build Coastguard Worker SkImage_Lazy::SkImage_Lazy(Validator* validator)
104*c8dee2aaSAndroid Build Coastguard Worker     : SkImage_Base(validator->fInfo, validator->fUniqueID)
105*c8dee2aaSAndroid Build Coastguard Worker     , fSharedGenerator(std::move(validator->fSharedGenerator))
106*c8dee2aaSAndroid Build Coastguard Worker {
107*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fSharedGenerator);
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker 
getROPixels(GrDirectContext * ctx,SkBitmap * bitmap,SkImage::CachingHint chint) const110*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Lazy::getROPixels(GrDirectContext* ctx, SkBitmap* bitmap,
111*c8dee2aaSAndroid Build Coastguard Worker                                SkImage::CachingHint chint) const {
112*c8dee2aaSAndroid Build Coastguard Worker     auto check_output_bitmap = [bitmap]() {
113*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(bitmap->isImmutable());
114*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(bitmap->getPixels());
115*c8dee2aaSAndroid Build Coastguard Worker         (void)bitmap;
116*c8dee2aaSAndroid Build Coastguard Worker     };
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker     auto desc = SkBitmapCacheDesc::Make(this);
119*c8dee2aaSAndroid Build Coastguard Worker     if (SkBitmapCache::Find(desc, bitmap)) {
120*c8dee2aaSAndroid Build Coastguard Worker         check_output_bitmap();
121*c8dee2aaSAndroid Build Coastguard Worker         return true;
122*c8dee2aaSAndroid Build Coastguard Worker     }
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     if (SkImage::kAllow_CachingHint == chint) {
125*c8dee2aaSAndroid Build Coastguard Worker         SkPixmap pmap;
126*c8dee2aaSAndroid Build Coastguard Worker         SkBitmapCache::RecPtr cacheRec = SkBitmapCache::Alloc(desc, this->imageInfo(), &pmap);
127*c8dee2aaSAndroid Build Coastguard Worker         if (!cacheRec) {
128*c8dee2aaSAndroid Build Coastguard Worker             return false;
129*c8dee2aaSAndroid Build Coastguard Worker         }
130*c8dee2aaSAndroid Build Coastguard Worker         bool success = false;
131*c8dee2aaSAndroid Build Coastguard Worker         {   // make sure ScopedGenerator goes out of scope before we try readPixelsProxy
132*c8dee2aaSAndroid Build Coastguard Worker             success = ScopedGenerator(fSharedGenerator)->getPixels(pmap);
133*c8dee2aaSAndroid Build Coastguard Worker         }
134*c8dee2aaSAndroid Build Coastguard Worker         if (!success && !this->readPixelsProxy(ctx, pmap)) {
135*c8dee2aaSAndroid Build Coastguard Worker             return false;
136*c8dee2aaSAndroid Build Coastguard Worker         }
137*c8dee2aaSAndroid Build Coastguard Worker         SkBitmapCache::Add(std::move(cacheRec), bitmap);
138*c8dee2aaSAndroid Build Coastguard Worker         this->notifyAddedToRasterCache();
139*c8dee2aaSAndroid Build Coastguard Worker     } else {
140*c8dee2aaSAndroid Build Coastguard Worker         if (!bitmap->tryAllocPixels(this->imageInfo())) {
141*c8dee2aaSAndroid Build Coastguard Worker             return false;
142*c8dee2aaSAndroid Build Coastguard Worker         }
143*c8dee2aaSAndroid Build Coastguard Worker         bool success = false;
144*c8dee2aaSAndroid Build Coastguard Worker         {   // make sure ScopedGenerator goes out of scope before we try readPixelsProxy
145*c8dee2aaSAndroid Build Coastguard Worker             success = ScopedGenerator(fSharedGenerator)->getPixels(bitmap->pixmap());
146*c8dee2aaSAndroid Build Coastguard Worker         }
147*c8dee2aaSAndroid Build Coastguard Worker         if (!success && !this->readPixelsProxy(ctx, bitmap->pixmap())) {
148*c8dee2aaSAndroid Build Coastguard Worker             return false;
149*c8dee2aaSAndroid Build Coastguard Worker         }
150*c8dee2aaSAndroid Build Coastguard Worker         bitmap->setImmutable();
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker     check_output_bitmap();
153*c8dee2aaSAndroid Build Coastguard Worker     return true;
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker 
generator() const156*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SharedGenerator> SkImage_Lazy::generator() const {
157*c8dee2aaSAndroid Build Coastguard Worker     return fSharedGenerator;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker 
onIsProtected() const160*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Lazy::onIsProtected() const {
161*c8dee2aaSAndroid Build Coastguard Worker     ScopedGenerator generator(fSharedGenerator);
162*c8dee2aaSAndroid Build Coastguard Worker     return generator->isProtected();
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker 
onReadPixels(GrDirectContext * dContext,const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,int srcX,int srcY,CachingHint chint) const165*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Lazy::onReadPixels(GrDirectContext* dContext,
166*c8dee2aaSAndroid Build Coastguard Worker                                 const SkImageInfo& dstInfo,
167*c8dee2aaSAndroid Build Coastguard Worker                                 void* dstPixels,
168*c8dee2aaSAndroid Build Coastguard Worker                                 size_t dstRB,
169*c8dee2aaSAndroid Build Coastguard Worker                                 int srcX,
170*c8dee2aaSAndroid Build Coastguard Worker                                 int srcY,
171*c8dee2aaSAndroid Build Coastguard Worker                                 CachingHint chint) const {
172*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm;
173*c8dee2aaSAndroid Build Coastguard Worker     if (this->getROPixels(dContext, &bm, chint)) {
174*c8dee2aaSAndroid Build Coastguard Worker         return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
175*c8dee2aaSAndroid Build Coastguard Worker     }
176*c8dee2aaSAndroid Build Coastguard Worker     return false;
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker 
onRefEncoded() const179*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> SkImage_Lazy::onRefEncoded() const {
180*c8dee2aaSAndroid Build Coastguard Worker     // check that we aren't a subset or colortype/etc modification of the original
181*c8dee2aaSAndroid Build Coastguard Worker     if (fSharedGenerator->fGenerator->uniqueID() == this->uniqueID()) {
182*c8dee2aaSAndroid Build Coastguard Worker         ScopedGenerator generator(fSharedGenerator);
183*c8dee2aaSAndroid Build Coastguard Worker         return generator->refEncodedData();
184*c8dee2aaSAndroid Build Coastguard Worker     }
185*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker 
isValid(GrRecordingContext * context) const188*c8dee2aaSAndroid Build Coastguard Worker bool SkImage_Lazy::isValid(GrRecordingContext* context) const {
189*c8dee2aaSAndroid Build Coastguard Worker     ScopedGenerator generator(fSharedGenerator);
190*c8dee2aaSAndroid Build Coastguard Worker     return generator->isValid(context);
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSubset(GrDirectContext *,const SkIRect & subset) const194*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Lazy::onMakeSubset(GrDirectContext*, const SkIRect& subset) const {
195*c8dee2aaSAndroid Build Coastguard Worker     // neither picture-backed nor codec-backed lazy images need the context to do readbacks.
196*c8dee2aaSAndroid Build Coastguard Worker     // The subclass for cross-context images *does* use the direct context.
197*c8dee2aaSAndroid Build Coastguard Worker     auto pixels = this->makeRasterImage(nullptr);
198*c8dee2aaSAndroid Build Coastguard Worker     return pixels ? pixels->makeSubset(nullptr, subset) : nullptr;
199*c8dee2aaSAndroid Build Coastguard Worker }
200*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSubset(skgpu::graphite::Recorder *,const SkIRect & subset,RequiredProperties props) const201*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Lazy::onMakeSubset(skgpu::graphite::Recorder*,
202*c8dee2aaSAndroid Build Coastguard Worker                                           const SkIRect& subset,
203*c8dee2aaSAndroid Build Coastguard Worker                                           RequiredProperties props) const {
204*c8dee2aaSAndroid Build Coastguard Worker     // TODO: can we do this more efficiently, by telling the generator we want to
205*c8dee2aaSAndroid Build Coastguard Worker     //       "realize" a subset?
206*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> nonLazyImg = this->makeRasterImage(nullptr);
207*c8dee2aaSAndroid Build Coastguard Worker     if (!nonLazyImg) {
208*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker     return nonLazyImg->makeSubset(nullptr, subset, props);
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker 
onMakeSurface(skgpu::graphite::Recorder *,const SkImageInfo & info) const213*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> SkImage_Lazy::onMakeSurface(skgpu::graphite::Recorder*,
214*c8dee2aaSAndroid Build Coastguard Worker                                              const SkImageInfo& info) const {
215*c8dee2aaSAndroid Build Coastguard Worker     const SkSurfaceProps* props = nullptr;
216*c8dee2aaSAndroid Build Coastguard Worker     const size_t rowBytes = 0;
217*c8dee2aaSAndroid Build Coastguard Worker     return SkSurfaces::Raster(info, rowBytes, props);
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker 
onMakeColorTypeAndColorSpace(SkColorType targetCT,sk_sp<SkColorSpace> targetCS,GrDirectContext *) const220*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace(SkColorType targetCT,
221*c8dee2aaSAndroid Build Coastguard Worker                                                           sk_sp<SkColorSpace> targetCS,
222*c8dee2aaSAndroid Build Coastguard Worker                                                           GrDirectContext*) const {
223*c8dee2aaSAndroid Build Coastguard Worker     SkAutoMutexExclusive autoAquire(fOnMakeColorTypeAndSpaceMutex);
224*c8dee2aaSAndroid Build Coastguard Worker     if (fOnMakeColorTypeAndSpaceResult &&
225*c8dee2aaSAndroid Build Coastguard Worker         targetCT == fOnMakeColorTypeAndSpaceResult->colorType() &&
226*c8dee2aaSAndroid Build Coastguard Worker         SkColorSpace::Equals(targetCS.get(), fOnMakeColorTypeAndSpaceResult->colorSpace())) {
227*c8dee2aaSAndroid Build Coastguard Worker         return fOnMakeColorTypeAndSpaceResult;
228*c8dee2aaSAndroid Build Coastguard Worker     }
229*c8dee2aaSAndroid Build Coastguard Worker     Validator validator(fSharedGenerator, &targetCT, targetCS);
230*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> result = validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr;
231*c8dee2aaSAndroid Build Coastguard Worker     if (result) {
232*c8dee2aaSAndroid Build Coastguard Worker         fOnMakeColorTypeAndSpaceResult = result;
233*c8dee2aaSAndroid Build Coastguard Worker     }
234*c8dee2aaSAndroid Build Coastguard Worker     return result;
235*c8dee2aaSAndroid Build Coastguard Worker }
236*c8dee2aaSAndroid Build Coastguard Worker 
onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const237*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> SkImage_Lazy::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
238*c8dee2aaSAndroid Build Coastguard Worker     // TODO: The correct thing is to clone the generator, and modify its color space. That's hard,
239*c8dee2aaSAndroid Build Coastguard Worker     // because we don't have a clone method, and generator is public (and derived-from by clients).
240*c8dee2aaSAndroid Build Coastguard Worker     // So do the simple/inefficient thing here, and fallback to raster when this is called.
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker     // We allocate the bitmap with the new color space, then generate the image using the original.
243*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bitmap;
244*c8dee2aaSAndroid Build Coastguard Worker     if (bitmap.tryAllocPixels(this->imageInfo().makeColorSpace(std::move(newCS)))) {
245*c8dee2aaSAndroid Build Coastguard Worker         SkPixmap pixmap = bitmap.pixmap();
246*c8dee2aaSAndroid Build Coastguard Worker         pixmap.setColorSpace(this->refColorSpace());
247*c8dee2aaSAndroid Build Coastguard Worker         if (ScopedGenerator(fSharedGenerator)->getPixels(pixmap)) {
248*c8dee2aaSAndroid Build Coastguard Worker             bitmap.setImmutable();
249*c8dee2aaSAndroid Build Coastguard Worker             return bitmap.asImage();
250*c8dee2aaSAndroid Build Coastguard Worker         }
251*c8dee2aaSAndroid Build Coastguard Worker     }
252*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker 
getPlanes(const SkYUVAPixmapInfo::SupportedDataTypes & supportedDataTypes,SkYUVAPixmaps * yuvaPixmaps) const255*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkCachedData> SkImage_Lazy::getPlanes(
256*c8dee2aaSAndroid Build Coastguard Worker         const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
257*c8dee2aaSAndroid Build Coastguard Worker         SkYUVAPixmaps* yuvaPixmaps) const {
258*c8dee2aaSAndroid Build Coastguard Worker     ScopedGenerator generator(fSharedGenerator);
259*c8dee2aaSAndroid Build Coastguard Worker 
260*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkCachedData> data(SkYUVPlanesCache::FindAndRef(generator->uniqueID(), yuvaPixmaps));
261*c8dee2aaSAndroid Build Coastguard Worker 
262*c8dee2aaSAndroid Build Coastguard Worker     if (data) {
263*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(yuvaPixmaps->isValid());
264*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(yuvaPixmaps->yuvaInfo().dimensions() == this->dimensions());
265*c8dee2aaSAndroid Build Coastguard Worker         return data;
266*c8dee2aaSAndroid Build Coastguard Worker     }
267*c8dee2aaSAndroid Build Coastguard Worker     SkYUVAPixmapInfo yuvaPixmapInfo;
268*c8dee2aaSAndroid Build Coastguard Worker     if (!generator->queryYUVAInfo(supportedDataTypes, &yuvaPixmapInfo) ||
269*c8dee2aaSAndroid Build Coastguard Worker         yuvaPixmapInfo.yuvaInfo().dimensions() != this->dimensions()) {
270*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
271*c8dee2aaSAndroid Build Coastguard Worker     }
272*c8dee2aaSAndroid Build Coastguard Worker     data.reset(SkResourceCache::NewCachedData(yuvaPixmapInfo.computeTotalBytes()));
273*c8dee2aaSAndroid Build Coastguard Worker     SkYUVAPixmaps tempPixmaps = SkYUVAPixmaps::FromExternalMemory(yuvaPixmapInfo,
274*c8dee2aaSAndroid Build Coastguard Worker                                                                   data->writable_data());
275*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(tempPixmaps.isValid());
276*c8dee2aaSAndroid Build Coastguard Worker     if (!generator->getYUVAPlanes(tempPixmaps)) {
277*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
278*c8dee2aaSAndroid Build Coastguard Worker     }
279*c8dee2aaSAndroid Build Coastguard Worker     // Decoding is done, cache the resulting YUV planes
280*c8dee2aaSAndroid Build Coastguard Worker     *yuvaPixmaps = tempPixmaps;
281*c8dee2aaSAndroid Build Coastguard Worker     SkYUVPlanesCache::Add(this->uniqueID(), data.get(), *yuvaPixmaps);
282*c8dee2aaSAndroid Build Coastguard Worker     return data;
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker 
addUniqueIDListener(sk_sp<SkIDChangeListener> listener) const285*c8dee2aaSAndroid Build Coastguard Worker void SkImage_Lazy::addUniqueIDListener(sk_sp<SkIDChangeListener> listener) const {
286*c8dee2aaSAndroid Build Coastguard Worker     fUniqueIDListeners.add(std::move(listener));
287*c8dee2aaSAndroid Build Coastguard Worker }
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick) move SharedGenerate to SkImage_Lazy.h and this to SkImage_LazyFactories
290*c8dee2aaSAndroid Build Coastguard Worker namespace SkImages {
291*c8dee2aaSAndroid Build Coastguard Worker 
DeferredFromGenerator(std::unique_ptr<SkImageGenerator> generator)292*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> DeferredFromGenerator(std::unique_ptr<SkImageGenerator> generator) {
293*c8dee2aaSAndroid Build Coastguard Worker     SkImage_Lazy::Validator validator(
294*c8dee2aaSAndroid Build Coastguard Worker             SharedGenerator::Make(std::move(generator)), nullptr, nullptr);
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker     return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr;
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker 
299*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkImages
300