@@ -61,27 +61,38 @@ class SharedGenerator final : public SkNVRefCnt<SharedGenerator> {
6161
6262// /////////////////////////////////////////////////////////////////////////////
6363
64- SkImage_Lazy::Validator::Validator (sk_sp<SharedGenerator> gen, const SkColorType* colorType ,
65- sk_sp<SkColorSpace> colorSpace)
64+ SkImage_Lazy::Validator::Validator (sk_sp<SharedGenerator> gen, const SkIRect* subset ,
65+ const SkColorType* colorType, sk_sp<SkColorSpace> colorSpace)
6666 : fSharedGenerator(std::move(gen)) {
6767 if (!fSharedGenerator ) {
6868 return ;
6969 }
7070
7171 // The following generator accessors are safe without acquiring the mutex (const getters).
7272 // TODO: refactor to use a ScopedGenerator instead, for clarity.
73- fInfo = fSharedGenerator ->fGenerator ->getInfo ();
74- if (fInfo .isEmpty ()) {
73+ const SkImageInfo& info = fSharedGenerator ->fGenerator ->getInfo ();
74+ if (info .isEmpty ()) {
7575 fSharedGenerator .reset ();
7676 return ;
7777 }
7878
7979 fUniqueID = fSharedGenerator ->fGenerator ->uniqueID ();
80-
81- if (colorType && (*colorType == fInfo .colorType ())) {
82- colorType = nullptr ;
80+ const SkIRect bounds = SkIRect::MakeWH (info.width (), info.height ());
81+ if (subset) {
82+ if (!bounds.contains (*subset)) {
83+ fSharedGenerator .reset ();
84+ return ;
85+ }
86+ if (*subset != bounds) {
87+ // we need a different uniqueID since we really are a subset of the raw generator
88+ fUniqueID = SkNextID::ImageID ();
89+ }
90+ } else {
91+ subset = &bounds;
8392 }
8493
94+ fInfo = info.makeDimensions (subset->size ());
95+ fOrigin = SkIPoint::Make (subset->x (), subset->y ());
8596 if (colorType || colorSpace) {
8697 if (colorType) {
8798 fInfo = fInfo .makeColorType (*colorType);
@@ -120,15 +131,51 @@ class SkImage_Lazy::ScopedGenerator {
120131// /////////////////////////////////////////////////////////////////////////////
121132
122133SkImage_Lazy::SkImage_Lazy (Validator* validator)
123- : INHERITED(validator->fInfo , validator->fUniqueID )
124- , fSharedGenerator(std::move(validator->fSharedGenerator ))
125- {
134+ : INHERITED(validator->fInfo , validator->fUniqueID )
135+ , fSharedGenerator(std::move(validator->fSharedGenerator ))
136+ , fOrigin(validator-> fOrigin ) {
126137 SkASSERT (fSharedGenerator );
127138}
128139
129140
130141// ////////////////////////////////////////////////////////////////////////////////////////////////
131142
143+ static bool generate_pixels (SkImageGenerator* gen, const SkPixmap& pmap, int originX, int originY) {
144+ const int genW = gen->getInfo ().width ();
145+ const int genH = gen->getInfo ().height ();
146+ const SkIRect srcR = SkIRect::MakeWH (genW, genH);
147+ const SkIRect dstR = SkIRect::MakeXYWH (originX, originY, pmap.width (), pmap.height ());
148+ if (!srcR.contains (dstR)) {
149+ return false ;
150+ }
151+
152+ // If they are requesting a subset, we have to have a temp allocation for full image, and
153+ // then copy the subset into their allocation
154+ SkBitmap full;
155+ SkPixmap fullPM;
156+ const SkPixmap* dstPM = &pmap;
157+ if (srcR != dstR) {
158+ if (!full.tryAllocPixels (pmap.info ().makeWH (genW, genH))) {
159+ return false ;
160+ }
161+ if (!full.peekPixels (&fullPM)) {
162+ return false ;
163+ }
164+ dstPM = &fullPM;
165+ }
166+
167+ if (!gen->getPixels (dstPM->info (), dstPM->writable_addr (), dstPM->rowBytes ())) {
168+ return false ;
169+ }
170+
171+ if (srcR != dstR) {
172+ if (!full.readPixels (pmap, originX, originY)) {
173+ return false ;
174+ }
175+ }
176+ return true ;
177+ }
178+
132179bool SkImage_Lazy::getROPixels (SkBitmap* bitmap, SkImage::CachingHint chint) const {
133180 auto check_output_bitmap = [bitmap]() {
134181 SkASSERT (bitmap->isImmutable ());
@@ -145,14 +192,17 @@ bool SkImage_Lazy::getROPixels(SkBitmap* bitmap, SkImage::CachingHint chint) con
145192 if (SkImage::kAllow_CachingHint == chint) {
146193 SkPixmap pmap;
147194 SkBitmapCache::RecPtr cacheRec = SkBitmapCache::Alloc (desc, this ->imageInfo (), &pmap);
148- if (!cacheRec || !ScopedGenerator (fSharedGenerator )->getPixels (pmap)) {
195+ if (!cacheRec ||
196+ !generate_pixels (ScopedGenerator (fSharedGenerator ), pmap,
197+ fOrigin .x (), fOrigin .y ())) {
149198 return false ;
150199 }
151200 SkBitmapCache::Add (std::move (cacheRec), bitmap);
152201 this ->notifyAddedToRasterCache ();
153202 } else {
154203 if (!bitmap->tryAllocPixels (this ->imageInfo ()) ||
155- !ScopedGenerator (fSharedGenerator )->getPixels (bitmap->pixmap ())) {
204+ !generate_pixels (ScopedGenerator (fSharedGenerator ), bitmap->pixmap (), fOrigin .x (),
205+ fOrigin .y ())) {
156206 return false ;
157207 }
158208 bitmap->setImmutable ();
@@ -196,13 +246,14 @@ GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrMipmappe
196246}
197247#endif
198248
199- sk_sp<SkImage> SkImage_Lazy::onMakeSubset (const SkIRect& subset, GrDirectContext* direct ) const {
200- // TODO: can we do this more efficiently, by telling the generator we want to
201- // "realize" a subset?
249+ sk_sp<SkImage> SkImage_Lazy::onMakeSubset (const SkIRect& subset, GrDirectContext*) const {
250+ SkASSERT ( this -> bounds (). contains (subset));
251+ SkASSERT ( this -> bounds () != subset);
202252
203- auto pixels = direct ? this ->makeTextureImage (direct)
204- : this ->makeRasterImage ();
205- return pixels ? pixels->makeSubset (subset, direct) : nullptr ;
253+ const SkIRect generatorSubset = subset.makeOffset (fOrigin );
254+ const SkColorType colorType = this ->colorType ();
255+ Validator validator (fSharedGenerator , &generatorSubset, &colorType, this ->refColorSpace ());
256+ return validator ? sk_sp<SkImage>(new SkImage_Lazy (&validator)) : nullptr ;
206257}
207258
208259sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace (SkColorType targetCT,
@@ -214,7 +265,9 @@ sk_sp<SkImage> SkImage_Lazy::onMakeColorTypeAndColorSpace(SkColorType targetCT,
214265 SkColorSpace::Equals (targetCS.get (), fOnMakeColorTypeAndSpaceResult ->colorSpace ())) {
215266 return fOnMakeColorTypeAndSpaceResult ;
216267 }
217- Validator validator (fSharedGenerator , &targetCT, targetCS);
268+ const SkIRect generatorSubset =
269+ SkIRect::MakeXYWH (fOrigin .x (), fOrigin .y (), this ->width (), this ->height ());
270+ Validator validator (fSharedGenerator , &generatorSubset, &targetCT, targetCS);
218271 sk_sp<SkImage> result = validator ? sk_sp<SkImage>(new SkImage_Lazy (&validator)) : nullptr ;
219272 if (result) {
220273 fOnMakeColorTypeAndSpaceResult = result;
@@ -232,7 +285,7 @@ sk_sp<SkImage> SkImage_Lazy::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS)
232285 if (bitmap.tryAllocPixels (this ->imageInfo ().makeColorSpace (std::move (newCS)))) {
233286 SkPixmap pixmap = bitmap.pixmap ();
234287 pixmap.setColorSpace (this ->refColorSpace ());
235- if (ScopedGenerator (fSharedGenerator )-> getPixels ( pixmap)) {
288+ if (generate_pixels ( ScopedGenerator (fSharedGenerator ), pixmap, fOrigin . x (), fOrigin . y () )) {
236289 bitmap.setImmutable ();
237290 return SkImage::MakeFromBitmap (bitmap);
238291 }
@@ -242,17 +295,47 @@ sk_sp<SkImage> SkImage_Lazy::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS)
242295
243296sk_sp<SkImage> SkImage::MakeFromGenerator (std::unique_ptr<SkImageGenerator> generator) {
244297 SkImage_Lazy::Validator
245- validator (SharedGenerator::Make (std::move (generator)), nullptr , nullptr );
298+ validator (SharedGenerator::Make (std::move (generator)), nullptr , nullptr , nullptr );
246299
247300 return validator ? sk_make_sp<SkImage_Lazy>(&validator) : nullptr ;
248301}
249302
250303sk_sp<SkImage> SkImage::DecodeToRaster (const void * encoded, size_t length, const SkIRect* subset) {
251- auto img = SkImage::MakeFromEncoded (SkData::MakeWithoutCopy (encoded, length));
252- if (img && subset) {
253- img = img->makeSubset (*subset);
304+ // The generator will not outlive this function, so we can wrap the encoded data without copy
305+ auto gen = SkImageGenerator::MakeFromEncoded (SkData::MakeWithoutCopy (encoded, length));
306+ if (!gen) {
307+ return nullptr ;
308+ }
309+ SkImageInfo info = gen->getInfo ();
310+ if (info.isEmpty ()) {
311+ return nullptr ;
312+ }
313+
314+ SkIPoint origin = {0 , 0 };
315+ if (subset) {
316+ if (!SkIRect::MakeWH (info.width (), info.height ()).contains (*subset)) {
317+ return nullptr ;
318+ }
319+ info = info.makeDimensions (subset->size ());
320+ origin = {subset->x (), subset->y ()};
321+ }
322+
323+ size_t rb = info.minRowBytes ();
324+ if (rb == 0 ) {
325+ return nullptr ; // rb was too big
326+ }
327+ size_t size = info.computeByteSize (rb);
328+ if (size == SIZE_MAX) {
329+ return nullptr ;
254330 }
255- return img ? img->makeRasterImage () : nullptr ;
331+ auto data = SkData::MakeUninitialized (size);
332+
333+ SkPixmap pmap (info, data->writable_data (), rb);
334+ if (!generate_pixels (gen.get (), pmap, origin.x (), origin.y ())) {
335+ return nullptr ;
336+ }
337+
338+ return SkImage::MakeRasterData (info, data, rb);
256339}
257340
258341// ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -514,7 +597,7 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
514597 // 2. Ask the generator to natively create one.
515598 {
516599 ScopedGenerator generator (fSharedGenerator );
517- if (auto view = generator->generateTexture (ctx, this ->imageInfo (), { 0 , 0 } , mipMapped,
600+ if (auto view = generator->generateTexture (ctx, this ->imageInfo (), fOrigin , mipMapped,
518601 texGenPolicy)) {
519602 SK_HISTOGRAM_ENUMERATION (" LockTexturePath" , kNative_LockTexturePath ,
520603 kLockTexturePathCount );
0 commit comments