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