diff options
author | Mike Klein <mtklein@chromium.org> | 2018-01-03 10:30:21 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-09 14:09:01 +0000 |
commit | c4616804bb407506c6ac1046c7e25e2016911449 (patch) | |
tree | 57897464bf5ac351818fad103d387671b823ec46 /src/shaders | |
parent | 0ee01901733aa4e1c3a1d1ff6d8d66425dca8402 (diff) |
alternate approach to unpremul scalePixels()
We want to keep the clamps in SkImageShader, and keep unpremul
scalePixels() happy too.
So we extend SkImageShader's internal API to allow specifying an output
alpha type, which controls whether we premul or unpremul and how we
clamp. scalePixels() uses this to draw instead of a drawBitmap() call.
Sort of backwards of usual, we opt our local builds into
SK_LEGACY_HIGH_QUALITY_SCALING_CLAMP (and Google3 is already defining
this). Then to rebase Chromium we will _define_ this in Chromium's user
config, fold it through as if always defined in Skia, then finally
remove the definition from Chromium's user config.
Change-Id: I38035f0886f79700e7301c3c6042ce362c771d96
Reviewed-on: https://skia-review.googlesource.com/90480
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/shaders')
-rw-r--r-- | src/shaders/SkImageShader.cpp | 46 | ||||
-rw-r--r-- | src/shaders/SkImageShader.h | 30 |
2 files changed, 48 insertions, 28 deletions
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp index 1f77158206..3e58782aee 100644 --- a/src/shaders/SkImageShader.cpp +++ b/src/shaders/SkImageShader.cpp @@ -31,23 +31,30 @@ static SkShader::TileMode optimize(SkShader::TileMode tm, int dimension) { #endif } -SkImageShader::SkImageShader(sk_sp<SkImage> img, TileMode tmx, TileMode tmy, const SkMatrix* matrix) - : INHERITED(matrix) +SkImageShader::SkImageShader(sk_sp<SkImage> img, + TileMode tmx, TileMode tmy, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType) + : INHERITED(localMatrix) , fImage(std::move(img)) , fTileModeX(optimize(tmx, fImage->width())) , fTileModeY(optimize(tmy, fImage->height())) + , fOutputAlphaType(outputAlphaType) {} +// fOutputAlphaType is always kPremul_SkAlphaType when an SkImageShader is constructed +// through public APIs that might lead to serialization, so we don't read or write it. + sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) { const TileMode tx = (TileMode)buffer.readUInt(); const TileMode ty = (TileMode)buffer.readUInt(); - SkMatrix matrix; - buffer.readMatrix(&matrix); + SkMatrix localMatrix; + buffer.readMatrix(&localMatrix); sk_sp<SkImage> img = buffer.readImage(); if (!img) { return nullptr; } - return SkImageShader::Make(std::move(img), tx, ty, &matrix); + return SkImageShader::Make(std::move(img), tx, ty, &localMatrix); } void SkImageShader::flatten(SkWriteBuffer& buffer) const { @@ -55,6 +62,7 @@ void SkImageShader::flatten(SkWriteBuffer& buffer) const { buffer.writeUInt(fTileModeY); buffer.writeMatrix(this->getLocalMatrix()); buffer.writeImage(fImage.get()); + SkASSERT(fOutputAlphaType == kPremul_SkAlphaType); } bool SkImageShader::isOpaque() const { @@ -164,13 +172,14 @@ static bool bitmap_is_too_big(int w, int h) { return w > kMaxSize || h > kMaxSize; } -sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, TileMode tx, TileMode ty, - const SkMatrix* localMatrix) { +sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, + TileMode tx, TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType) { if (!image || bitmap_is_too_big(image->width(), image->height())) { return sk_make_sp<SkEmptyShader>(); - } else { - return sk_make_sp<SkImageShader>(image, tx, ty, localMatrix); } + return sk_sp<SkShader>{ new SkImageShader(image, tx,ty, localMatrix, outputAlphaType) }; } #ifndef SK_IGNORE_TO_STRING @@ -385,19 +394,24 @@ bool SkImageShader::onAppendStages(const StageRec& rec) const { auto append_misc = [&] { if (info.colorType() == kAlpha_8_SkColorType) { p->append(SkRasterPipeline::set_rgb, &misc->paint_color); - } - if (info.colorType() == kAlpha_8_SkColorType || - info.alphaType() == kUnpremul_SkAlphaType) { p->append(SkRasterPipeline::premul); + } else if (info.alphaType() == kUnpremul_SkAlphaType && + fOutputAlphaType == kPremul_SkAlphaType) { + p->append(SkRasterPipeline::premul); + } else if (info.alphaType() == kPremul_SkAlphaType && + fOutputAlphaType == kUnpremul_SkAlphaType) { + p->append(SkRasterPipeline::unpremul); } -#if defined(SK_LEGACY_HIGH_QUALITY_SCALING_CLAMP) + + #if defined(SK_LEGACY_HIGH_QUALITY_SCALING_CLAMP) if (quality > kLow_SkFilterQuality) { // Bicubic filtering naturally produces out of range values on both sides. p->append(SkRasterPipeline::clamp_0); - p->append(SkRasterPipeline::clamp_a); + p->append(fOutputAlphaType == kPremul_SkAlphaType ? SkRasterPipeline::clamp_a + : SkRasterPipeline::clamp_1); } -#endif - append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, kPremul_SkAlphaType); + #endif + append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, fOutputAlphaType); return true; }; diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h index a3cf3dbe7f..9ce615508d 100644 --- a/src/shaders/SkImageShader.h +++ b/src/shaders/SkImageShader.h @@ -15,8 +15,11 @@ class SkImageShader : public SkShaderBase { public: - static sk_sp<SkShader> Make(sk_sp<SkImage>, TileMode tx, TileMode ty, - const SkMatrix* localMatrix); + static sk_sp<SkShader> Make(sk_sp<SkImage>, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType = kPremul_SkAlphaType); bool isOpaque() const override; @@ -27,19 +30,23 @@ public: std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override; #endif - SkImageShader(sk_sp<SkImage>, TileMode tx, TileMode ty, const SkMatrix* localMatrix); - static bool IsRasterPipelineOnly(const SkMatrix& ctm, SkColorType, SkAlphaType, SkShader::TileMode tx, SkShader::TileMode ty, const SkMatrix& localM); -protected: +private: + SkImageShader(sk_sp<SkImage>, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType); + void flatten(SkWriteBuffer&) const override; Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override; #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP - bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override; + bool onIsABitmap(SkBitmap*, SkMatrix*, SkShader::TileMode*) const override; #endif - SkImage* onIsAImage(SkMatrix*, TileMode*) const override; + SkImage* onIsAImage(SkMatrix*, SkShader::TileMode*) const override; bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override; @@ -50,13 +57,12 @@ protected: &this->getLocalMatrix()); } - sk_sp<SkImage> fImage; - const TileMode fTileModeX; - const TileMode fTileModeY; + sk_sp<SkImage> fImage; + const SkShader::TileMode fTileModeX; + const SkShader::TileMode fTileModeY; + const SkAlphaType fOutputAlphaType; -private: friend class SkShaderBase; - typedef SkShaderBase INHERITED; }; |