aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/image')
-rw-r--r--src/image/SkImage.cpp29
-rw-r--r--src/image/SkImageShader.cpp13
-rw-r--r--src/image/SkImage_Base.h5
-rw-r--r--src/image/SkImage_Generator.cpp22
-rw-r--r--src/image/SkImage_Gpu.cpp34
-rw-r--r--src/image/SkImage_Gpu.h4
-rw-r--r--src/image/SkImage_Raster.cpp13
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) {