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
8 #include "SkImage_Base.h"
9 #include "SkBitmap.h"
10 #include "SkData.h"
11 #include "SkImageCacherator.h"
12 #include "SkImagePriv.h"
13 #include "SkPixelRef.h"
14
15 class SkImage_Generator : public SkImage_Base {
16 public:
SkImage_Generator(SkImageCacherator::Validator * validator)17 SkImage_Generator(SkImageCacherator::Validator* validator)
18 : INHERITED(validator->fInfo.width(), validator->fInfo.height(), validator->fUniqueID)
19 , fCache(validator)
20 {}
21
onImageInfo() const22 virtual SkImageInfo onImageInfo() const override {
23 return fCache.info();
24 }
onAlphaType() const25 SkAlphaType onAlphaType() const override {
26 return fCache.info().alphaType();
27 }
28
29 bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
30 CachingHint) const override;
31 #if SK_SUPPORT_GPU
32 sk_sp<GrTextureProxy> asTextureProxyRef(GrContext*, const GrSamplerParams&,
33 SkColorSpace*, sk_sp<SkColorSpace>*,
34 SkScalar scaleAdjust[2]) const override;
35 #endif
peekCacherator() const36 SkImageCacherator* peekCacherator() const override { return &fCache; }
37 SkData* onRefEncoded(GrContext*) const override;
38 sk_sp<SkImage> onMakeSubset(const SkIRect&) const override;
39 bool getROPixels(SkBitmap*, SkColorSpace* dstColorSpace, CachingHint) const override;
onIsLazyGenerated() const40 bool onIsLazyGenerated() const override { return true; }
41 sk_sp<SkImage> onMakeColorSpace(sk_sp<SkColorSpace>) const override;
42
43 private:
44 mutable SkImageCacherator fCache;
45
46 typedef SkImage_Base INHERITED;
47 };
48
49 ///////////////////////////////////////////////////////////////////////////////
50
onReadPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,int srcX,int srcY,CachingHint chint) const51 bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
52 int srcX, int srcY, CachingHint chint) const {
53 SkColorSpace* dstColorSpace = dstInfo.colorSpace();
54 SkBitmap bm;
55 if (kDisallow_CachingHint == chint) {
56 SkImageCacherator::CachedFormat cacheFormat = fCache.chooseCacheFormat(dstColorSpace);
57 if (fCache.lockAsBitmapOnlyIfAlreadyCached(&bm, cacheFormat)) {
58 return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
59 } else {
60 // Try passing the caller's buffer directly down to the generator. If this fails we
61 // may still succeed in the general case, as the generator may prefer some other
62 // config, which we could then convert via SkBitmap::readPixels.
63 if (fCache.directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY)) {
64 return true;
65 }
66 // else fall through
67 }
68 }
69
70 if (this->getROPixels(&bm, dstColorSpace, chint)) {
71 return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
72 }
73 return false;
74 }
75
onRefEncoded(GrContext * ctx) const76 SkData* SkImage_Generator::onRefEncoded(GrContext* ctx) const {
77 return fCache.refEncoded(ctx);
78 }
79
getROPixels(SkBitmap * bitmap,SkColorSpace * dstColorSpace,CachingHint chint) const80 bool SkImage_Generator::getROPixels(SkBitmap* bitmap, SkColorSpace* dstColorSpace,
81 CachingHint chint) const {
82 return fCache.lockAsBitmap(nullptr, bitmap, this, dstColorSpace, chint);
83 }
84
85 #if SK_SUPPORT_GPU
asTextureProxyRef(GrContext * context,const GrSamplerParams & params,SkColorSpace * dstColorSpace,sk_sp<SkColorSpace> * texColorSpace,SkScalar scaleAdjust[2]) const86 sk_sp<GrTextureProxy> SkImage_Generator::asTextureProxyRef(GrContext* context,
87 const GrSamplerParams& params,
88 SkColorSpace* dstColorSpace,
89 sk_sp<SkColorSpace>* texColorSpace,
90 SkScalar scaleAdjust[2]) const {
91 return fCache.lockAsTextureProxy(context, params, dstColorSpace,
92 texColorSpace, this, scaleAdjust);
93 }
94 #endif
95
onMakeSubset(const SkIRect & subset) const96 sk_sp<SkImage> SkImage_Generator::onMakeSubset(const SkIRect& subset) const {
97 SkASSERT(fCache.info().bounds().contains(subset));
98 SkASSERT(fCache.info().bounds() != subset);
99
100 const SkIRect generatorSubset = subset.makeOffset(fCache.fOrigin.x(), fCache.fOrigin.y());
101 SkImageCacherator::Validator validator(fCache.fSharedGenerator, &generatorSubset);
102 return validator ? sk_sp<SkImage>(new SkImage_Generator(&validator)) : nullptr;
103 }
104
onMakeColorSpace(sk_sp<SkColorSpace> target) const105 sk_sp<SkImage> SkImage_Generator::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
106 SkBitmap dst;
107 SkImageInfo dstInfo = fCache.info().makeColorSpace(target);
108 if (kIndex_8_SkColorType == dstInfo.colorType() ||
109 kGray_8_SkColorType == dstInfo.colorType()) {
110 dstInfo = dstInfo.makeColorType(kN32_SkColorType);
111 }
112 dst.allocPixels(dstInfo);
113
114 if (!fCache.directGeneratePixels(dstInfo, dst.getPixels(), dst.rowBytes(), 0, 0)) {
115 return nullptr;
116 }
117
118 dst.setImmutable();
119 return SkImage::MakeFromBitmap(dst);
120 }
121
MakeFromGenerator(std::unique_ptr<SkImageGenerator> generator,const SkIRect * subset)122 sk_sp<SkImage> SkImage::MakeFromGenerator(std::unique_ptr<SkImageGenerator> generator,
123 const SkIRect* subset) {
124 SkImageCacherator::Validator validator(
125 SkImageCacherator::SharedGenerator::Make(std::move(generator)), subset);
126
127 return validator ? sk_make_sp<SkImage_Generator>(&validator) : nullptr;
128 }
129