diff options
Diffstat (limited to 'src/image')
-rw-r--r-- | src/image/SkImage.cpp | 29 | ||||
-rw-r--r-- | src/image/SkImageShader.cpp | 13 | ||||
-rw-r--r-- | src/image/SkImage_Base.h | 5 | ||||
-rw-r--r-- | src/image/SkImage_Generator.cpp | 22 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 34 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.h | 4 | ||||
-rw-r--r-- | src/image/SkImage_Raster.cpp | 13 |
7 files changed, 85 insertions, 35 deletions
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index 4d76638cbd..f976242eca 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -65,8 +65,11 @@ bool SkImage::scalePixels(const SkPixmap& dst, SkFilterQuality quality, CachingH // Idea: If/when SkImageGenerator supports a native-scaling API (where the generator itself // can scale more efficiently) we should take advantage of it here. // + SkDestinationSurfaceColorMode decodeColorMode = dst.info().colorSpace() + ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware + : SkDestinationSurfaceColorMode::kLegacy; SkBitmap bm; - if (as_IB(this)->getROPixels(&bm, chint)) { + if (as_IB(this)->getROPixels(&bm, decodeColorMode, chint)) { bm.lockPixels(); SkPixmap pmap; // Note: By calling the pixmap scaler, we never cache the final result, so the chint @@ -83,7 +86,7 @@ void SkImage::preroll(GrContext* ctx) const { // to produce a cached raster-bitmap form, so that drawing to a raster canvas should be fast. // SkBitmap bm; - if (as_IB(this)->getROPixels(&bm)) { + if (as_IB(this)->getROPixels(&bm, SkDestinationSurfaceColorMode::kLegacy)) { bm.lockPixels(); bm.unlockPixels(); } @@ -102,7 +105,10 @@ sk_sp<SkShader> SkImage::makeShader(SkShader::TileMode tileX, SkShader::TileMode SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const { SkBitmap bm; - if (as_IB(this)->getROPixels(&bm)) { + // TODO: Right now, the encoders don't handle F16 or linearly premultiplied data. Once they do, + // we should decode in "color space aware" mode, then re-encode that. For now, work around this + // by asking for a legacy decode (which gives us the raw data in N32). + if (as_IB(this)->getROPixels(&bm, SkDestinationSurfaceColorMode::kLegacy)) { return SkImageEncoder::EncodeData(bm, type, quality); } return nullptr; @@ -123,7 +129,11 @@ SkData* SkImage::encode(SkPixelSerializer* serializer) const { SkBitmap bm; SkAutoPixmapUnlock apu; - if (as_IB(this)->getROPixels(&bm) && bm.requestLock(&apu)) { + // TODO: Right now, the encoders don't handle F16 or linearly premultiplied data. Once they do, + // we should decode in "color space aware" mode, then re-encode that. For now, work around this + // by asking for a legacy decode (which gives us the raw data in N32). + if (as_IB(this)->getROPixels(&bm, SkDestinationSurfaceColorMode::kLegacy) && + bm.requestLock(&apu)) { return effectiveSerializer->encode(apu.pixmap()); } @@ -284,8 +294,7 @@ bool SkImage::asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const { bool SkImage_Base::onAsLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode mode) const { // As the base-class, all we can do is make a copy (regardless of mode). // Subclasses that want to be more optimal should override. - SkImageInfo info = this->onImageInfo().makeColorType(kN32_SkColorType) - .makeAlphaType(this->alphaType()); + SkImageInfo info = this->onImageInfo().makeColorType(kN32_SkColorType).makeColorSpace(nullptr); if (!bitmap->tryAllocPixels(info)) { return false; } @@ -315,15 +324,19 @@ sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRec if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) { return nullptr; } + SkColorSpace* colorSpace = as_IB(this)->onImageInfo().colorSpace(); + SkDestinationSurfaceColorMode decodeColorMode = colorSpace + ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware + : SkDestinationSurfaceColorMode::kLegacy; sk_sp<SkSpecialImage> srcSpecialImage = SkSpecialImage::MakeFromImage( - subset, sk_ref_sp(const_cast<SkImage*>(this))); + subset, sk_ref_sp(const_cast<SkImage*>(this)), decodeColorMode); if (!srcSpecialImage) { return nullptr; } sk_sp<SkImageFilterCache> cache( SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize)); - SkImageFilter::OutputProperties outputProperties(as_IB(this)->onImageInfo().colorSpace()); + SkImageFilter::OutputProperties outputProperties(colorSpace); SkImageFilter::Context context(SkMatrix::I(), clipBounds, cache.get(), outputProperties); sk_sp<SkSpecialImage> result = diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp index 81b6f76ede..f8b22df41a 100644 --- a/src/image/SkImageShader.cpp +++ b/src/image/SkImageShader.cpp @@ -52,8 +52,12 @@ size_t SkImageShader::onContextSize(const ContextRec& rec) const { } SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const { + // TODO: This is wrong. We should be plumbing destination color space to context creation, + // and use that to determine the decoding mode of the image. + SkDestinationSurfaceColorMode decodeColorMode = SkMipMap::DeduceColorMode(rec); return SkBitmapProcLegacyShader::MakeContext(*this, fTileModeX, fTileModeY, - SkBitmapProvider(fImage.get()), rec, storage); + SkBitmapProvider(fImage.get(), decodeColorMode), + rec, storage); } SkImage* SkImageShader::onIsAImage(SkMatrix* texM, TileMode xy[]) const { @@ -211,13 +215,14 @@ sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& ar GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatrix, this->getLocalMatrix(), &doBicubic); GrSamplerParams params(tm, textureFilterMode); - sk_sp<GrTexture> texture(as_IB(fImage)->asTextureRef(args.fContext, params, args.fColorMode)); + sk_sp<SkColorSpace> texColorSpace; + sk_sp<GrTexture> texture(as_IB(fImage)->asTextureRef(args.fContext, params, args.fColorMode, + &texColorSpace)); if (!texture) { return nullptr; } - SkImageInfo info = as_IB(fImage)->onImageInfo(); - sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(info.colorSpace(), + sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(), args.fDstColorSpace); sk_sp<GrFragmentProcessor> inner; if (doBicubic) { diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h index 09ceb5770a..c955d491f7 100644 --- a/src/image/SkImage_Base.h +++ b/src/image/SkImage_Base.h @@ -52,11 +52,12 @@ public: // return a read-only copy of the pixels. We promise to not modify them, // but only inspect them (or encode them). - virtual bool getROPixels(SkBitmap*, CachingHint = kAllow_CachingHint) const = 0; + virtual bool getROPixels(SkBitmap*, SkDestinationSurfaceColorMode, + CachingHint = kAllow_CachingHint) const = 0; // Caller must call unref when they are done. virtual GrTexture* asTextureRef(GrContext*, const GrSamplerParams&, - SkDestinationSurfaceColorMode) const = 0; + SkDestinationSurfaceColorMode, sk_sp<SkColorSpace>*) const = 0; virtual sk_sp<SkImage> onMakeSubset(const SkIRect&) const = 0; diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp index 82f395fc95..efee134a81 100644 --- a/src/image/SkImage_Generator.cpp +++ b/src/image/SkImage_Generator.cpp @@ -30,9 +30,9 @@ public: SkImageCacherator* peekCacherator() const override { return &fCache; } SkData* onRefEncoded(GrContext*) const override; sk_sp<SkImage> onMakeSubset(const SkIRect&) const override; - bool getROPixels(SkBitmap*, CachingHint) const override; + bool getROPixels(SkBitmap*, SkDestinationSurfaceColorMode, CachingHint) const override; GrTexture* asTextureRef(GrContext*, const GrSamplerParams&, - SkDestinationSurfaceColorMode) const override; + SkDestinationSurfaceColorMode, sk_sp<SkColorSpace>*) const override; bool onIsLazyGenerated() const override { return true; } private: @@ -45,9 +45,13 @@ private: bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int srcX, int srcY, CachingHint chint) const { + SkDestinationSurfaceColorMode decodeColorMode = dstInfo.colorSpace() + ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware + : SkDestinationSurfaceColorMode::kLegacy; SkBitmap bm; if (kDisallow_CachingHint == chint) { - if (fCache.lockAsBitmapOnlyIfAlreadyCached(&bm)) { + SkImageCacherator::CachedFormat cacheFormat = fCache.chooseCacheFormat(decodeColorMode); + if (fCache.lockAsBitmapOnlyIfAlreadyCached(&bm, cacheFormat)) { return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY); } else { // Try passing the caller's buffer directly down to the generator. If this fails we @@ -60,7 +64,7 @@ bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels } } - if (this->getROPixels(&bm, chint)) { + if (this->getROPixels(&bm, decodeColorMode, chint)) { return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY); } return false; @@ -70,13 +74,15 @@ SkData* SkImage_Generator::onRefEncoded(GrContext* ctx) const { return fCache.refEncoded(ctx); } -bool SkImage_Generator::getROPixels(SkBitmap* bitmap, CachingHint chint) const { - return fCache.lockAsBitmap(bitmap, this, chint); +bool SkImage_Generator::getROPixels(SkBitmap* bitmap, SkDestinationSurfaceColorMode colorMode, + CachingHint chint) const { + return fCache.lockAsBitmap(bitmap, this, colorMode, chint); } GrTexture* SkImage_Generator::asTextureRef(GrContext* ctx, const GrSamplerParams& params, - SkDestinationSurfaceColorMode colorMode) const { - return fCache.lockAsTexture(ctx, params, colorMode, this); + SkDestinationSurfaceColorMode colorMode, + sk_sp<SkColorSpace>* texColorSpace) const { + return fCache.lockAsTexture(ctx, params, colorMode, texColorSpace, this); } sk_sp<SkImage> SkImage_Generator::onMakeSubset(const SkIRect& subset) const { diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index 84c7b10be1..02f4d69519 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -20,6 +20,7 @@ #include "SkBitmapCache.h" #include "SkGrPriv.h" #include "SkImage_Gpu.h" +#include "SkImageCacherator.h" #include "SkMipMap.h" #include "SkPixelRef.h" @@ -60,7 +61,8 @@ static SkImageInfo make_info(int w, int h, SkAlphaType at, sk_sp<SkColorSpace> c return SkImageInfo::MakeN32(w, h, at, std::move(colorSpace)); } -bool SkImage_Gpu::getROPixels(SkBitmap* dst, CachingHint chint) const { +bool SkImage_Gpu::getROPixels(SkBitmap* dst, SkDestinationSurfaceColorMode, + CachingHint chint) const { if (SkBitmapCache::Find(this->uniqueID(), dst)) { SkASSERT(dst->getGenerationID() == this->uniqueID()); SkASSERT(dst->isImmutable()); @@ -86,9 +88,13 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst, CachingHint chint) const { } GrTexture* SkImage_Gpu::asTextureRef(GrContext* ctx, const GrSamplerParams& params, - SkDestinationSurfaceColorMode colorMode) const { - GrTextureAdjuster adjuster(this->peekTexture(), this->alphaType(), this->bounds(), this->uniqueID(), - this->onImageInfo().colorSpace()); + SkDestinationSurfaceColorMode colorMode, + sk_sp<SkColorSpace>* texColorSpace) const { + if (texColorSpace) { + *texColorSpace = this->fColorSpace; + } + GrTextureAdjuster adjuster(this->peekTexture(), this->alphaType(), this->bounds(), + this->uniqueID(), this->fColorSpace.get()); return adjuster.refTextureSafeForParams(params, colorMode, nullptr); } @@ -298,14 +304,16 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace } static sk_sp<SkImage> create_image_from_maker(GrTextureMaker* maker, SkAlphaType at, uint32_t id) { + sk_sp<SkColorSpace> texColorSpace; sk_sp<GrTexture> texture( maker->refTextureForParams(GrSamplerParams::ClampNoFilter(), - SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware)); + SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware, + &texColorSpace)); if (!texture) { return nullptr; } return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), id, at, std::move(texture), - sk_ref_sp(maker->getColorSpace()), SkBudgeted::kNo); + std::move(texColorSpace), SkBudgeted::kNo); } sk_sp<SkImage> SkImage::makeTextureImage(GrContext *context) const { @@ -498,7 +506,19 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox if (!data && !this->peekPixels(nullptr)) { return 0; } - info = as_IB(this)->onImageInfo().makeWH(scaledSize.width(), scaledSize.height()); + if (SkImageCacherator* cacher = as_IB(this)->peekCacherator()) { + // Generator backed image. Tweak info to trigger correct kind of decode. + SkDestinationSurfaceColorMode decodeColorMode = dstColorSpace + ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware + : SkDestinationSurfaceColorMode::kLegacy; + SkImageCacherator::CachedFormat cacheFormat = cacher->chooseCacheFormat( + decodeColorMode, proxy.fCaps.get()); + info = cacher->buildCacheInfo(cacheFormat).makeWH(scaledSize.width(), + scaledSize.height()); + + } else { + info = as_IB(this)->onImageInfo().makeWH(scaledSize.width(), scaledSize.height()); + } pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr)); if (fillMode) { pixmap.alloc(info); diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h index 19e2944283..dcde00a8fc 100644 --- a/src/image/SkImage_Gpu.h +++ b/src/image/SkImage_Gpu.h @@ -38,9 +38,9 @@ public: } } - bool getROPixels(SkBitmap*, CachingHint) const override; + bool getROPixels(SkBitmap*, SkDestinationSurfaceColorMode, CachingHint) const override; GrTexture* asTextureRef(GrContext* ctx, const GrSamplerParams& params, - SkDestinationSurfaceColorMode) const override; + SkDestinationSurfaceColorMode, sk_sp<SkColorSpace>*) const override; sk_sp<SkImage> onMakeSubset(const SkIRect&) const override; GrTexture* peekTexture() const override { return fTexture.get(); } diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp index a2b12e41ce..0875d615b0 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -88,9 +88,9 @@ public: const SkBitmap* onPeekBitmap() const override { return &fBitmap; } SkData* onRefEncoded(GrContext*) const override; - bool getROPixels(SkBitmap*, CachingHint) const override; + bool getROPixels(SkBitmap*, SkDestinationSurfaceColorMode, CachingHint) const override; GrTexture* asTextureRef(GrContext*, const GrSamplerParams&, - SkDestinationSurfaceColorMode) const override; + SkDestinationSurfaceColorMode, sk_sp<SkColorSpace>*) const override; sk_sp<SkImage> onMakeSubset(const SkIRect&) const override; // exposed for SkSurface_Raster via SkNewImageFromPixelRef @@ -192,18 +192,23 @@ SkData* SkImage_Raster::onRefEncoded(GrContext*) const { return nullptr; } -bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const { +bool SkImage_Raster::getROPixels(SkBitmap* dst, SkDestinationSurfaceColorMode, CachingHint) const { *dst = fBitmap; return true; } GrTexture* SkImage_Raster::asTextureRef(GrContext* ctx, const GrSamplerParams& params, - SkDestinationSurfaceColorMode colorMode) const { + SkDestinationSurfaceColorMode colorMode, + sk_sp<SkColorSpace>* texColorSpace) const { #if SK_SUPPORT_GPU if (!ctx) { return nullptr; } + if (texColorSpace) { + *texColorSpace = sk_ref_sp(fBitmap.colorSpace()); + } + uint32_t uniqueID; sk_sp<GrTexture> tex = this->refPinnedTexture(&uniqueID); if (tex) { |