aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2018-01-03 10:30:21 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-09 14:09:01 +0000
commitc4616804bb407506c6ac1046c7e25e2016911449 (patch)
tree57897464bf5ac351818fad103d387671b823ec46 /src/shaders
parent0ee01901733aa4e1c3a1d1ff6d8d66425dca8402 (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.cpp46
-rw-r--r--src/shaders/SkImageShader.h30
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;
};