aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2018-02-09 18:57:54 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-09 18:58:02 +0000
commit47cf048abecb5064b9e851ea01f75b23797c1611 (patch)
tree3d838684c3c54ac61560c57972bff55d834ee04e /src
parent96c572500a18d6f1ad1c179fc36323df64e7e16c (diff)
Revert "alternate approach to unpremul scalePixels()"
This reverts commit c4616804bb407506c6ac1046c7e25e2016911449. Reason for revert: screwed up the guard I think Original change's description: > 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> TBR=mtklein@chromium.org,mtklein@google.com,brianosman@google.com,reed@google.com Change-Id: Ib53a7f29c25310b667f9a61f67f8638403ec9da3 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/106220 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkPixmap.cpp67
-rw-r--r--src/shaders/SkImageShader.cpp46
-rw-r--r--src/shaders/SkImageShader.h30
3 files changed, 57 insertions, 86 deletions
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 050c6e2ab4..42e2c66029 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -11,7 +11,6 @@
#include "SkConvertPixels.h"
#include "SkData.h"
#include "SkImageInfoPriv.h"
-#include "SkImageShader.h"
#include "SkHalf.h"
#include "SkMask.h"
#include "SkNx.h"
@@ -230,6 +229,10 @@ bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const {
return true;
}
+static void set_alphatype(SkPixmap* dst, const SkPixmap& src, SkAlphaType at) {
+ dst->reset(src.info().makeAlphaType(at), src.addr(), src.rowBytes());
+}
+
bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const {
// Can't do anthing with empty src or dst
if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) {
@@ -241,51 +244,39 @@ bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const {
return this->readPixels(dst);
}
+ // Temp storage in case we need to edit the requested alphatypes
+ SkPixmap storage_src, storage_dst;
+ const SkPixmap* srcPtr = this;
+ const SkPixmap* dstPtr = &dst;
+
+ // Trick: if src and dst are both unpremul, we can give the correct result if we change both
+ // to premul (or opaque), since the draw will not try to blend or otherwise interpret
+ // the pixels' alpha.
+ if (srcPtr->alphaType() == kUnpremul_SkAlphaType &&
+ dstPtr->alphaType() == kUnpremul_SkAlphaType)
+ {
+ set_alphatype(&storage_src, *this, kPremul_SkAlphaType);
+ set_alphatype(&storage_dst, dst, kPremul_SkAlphaType);
+ srcPtr = &storage_src;
+ dstPtr = &storage_dst;
+ }
+
SkBitmap bitmap;
- if (!bitmap.installPixels(*this)) {
+ if (!bitmap.installPixels(*srcPtr)) {
return false;
}
- bitmap.setImmutable(); // Don't copy when we create an image.
- bitmap.setIsVolatile(true); // Disable any caching.
-
- // We're going to set this up a little oddly so that we can scale unpremul SkPixmaps
- // to unpremul dsts without ever premultiplying (and potentially throwing away information).
-
- // 1) Here's the scale matrix between our input pixels and the scaled destination.
- SkMatrix matrix = SkMatrix::MakeRectToRect(SkRect::Make(this->bounds()),
- SkRect::Make(dst.bounds()),
- SkMatrix::kFill_ScaleToFit);
-
-
- // 2) Instead of just calling drawBitmap(), we'll create a shader that carefully
- // keeps its output in the alpha type we request, dst.alphaType().
- sk_sp<SkShader> shader = SkImageShader::Make(SkImage::MakeFromBitmap(bitmap),
- SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode,
- &matrix,
- dst.alphaType());
-
- // 3) No matter what dst's actual alpha type is, we'll construct this surface
- // as if it were not unpremul. This keeps the rest of the drawing pipeline oblivious
- // to our trickery here, and prevents it from doing anything like a manual unpremul.
- SkImageInfo info = dst.info();
- if (info.alphaType() == kUnpremul_SkAlphaType) {
- info = info.makeAlphaType(kPremul_SkAlphaType);
- }
- sk_sp<SkSurface> surface =
- SkSurface::MakeRasterDirect(info, dst.writable_addr(), dst.rowBytes());
- if (!shader || !surface) {
+ bitmap.setIsVolatile(true); // so we don't try to cache it
+
+ auto surface(SkSurface::MakeRasterDirect(dstPtr->info(), dstPtr->writable_addr(), dstPtr->rowBytes()));
+ if (!surface) {
return false;
}
- // 4) Using SkBlendMode::kSrc means we won't be tempted to try any premul-only blending math.
SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
paint.setFilterQuality(quality);
- paint.setShader(std::move(shader));
-
- // 5) Draw it!
- surface->getCanvas()->drawPaint(paint);
+ paint.setBlendMode(SkBlendMode::kSrc);
+ surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()),
+ &paint);
return true;
}
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 3e58782aee..1f77158206 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -31,30 +31,23 @@ static SkShader::TileMode optimize(SkShader::TileMode tm, int dimension) {
#endif
}
-SkImageShader::SkImageShader(sk_sp<SkImage> img,
- TileMode tmx, TileMode tmy,
- const SkMatrix* localMatrix,
- SkAlphaType outputAlphaType)
- : INHERITED(localMatrix)
+SkImageShader::SkImageShader(sk_sp<SkImage> img, TileMode tmx, TileMode tmy, const SkMatrix* matrix)
+ : INHERITED(matrix)
, 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 localMatrix;
- buffer.readMatrix(&localMatrix);
+ SkMatrix matrix;
+ buffer.readMatrix(&matrix);
sk_sp<SkImage> img = buffer.readImage();
if (!img) {
return nullptr;
}
- return SkImageShader::Make(std::move(img), tx, ty, &localMatrix);
+ return SkImageShader::Make(std::move(img), tx, ty, &matrix);
}
void SkImageShader::flatten(SkWriteBuffer& buffer) const {
@@ -62,7 +55,6 @@ 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 {
@@ -172,14 +164,13 @@ 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,
- SkAlphaType outputAlphaType) {
+sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, TileMode tx, TileMode ty,
+ const SkMatrix* localMatrix) {
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
@@ -394,24 +385,19 @@ 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(fOutputAlphaType == kPremul_SkAlphaType ? SkRasterPipeline::clamp_a
- : SkRasterPipeline::clamp_1);
+ p->append(SkRasterPipeline::clamp_a);
}
- #endif
- append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, fOutputAlphaType);
+#endif
+ append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, kPremul_SkAlphaType);
return true;
};
diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h
index 9ce615508d..a3cf3dbe7f 100644
--- a/src/shaders/SkImageShader.h
+++ b/src/shaders/SkImageShader.h
@@ -15,11 +15,8 @@
class SkImageShader : public SkShaderBase {
public:
- static sk_sp<SkShader> Make(sk_sp<SkImage>,
- SkShader::TileMode tx,
- SkShader::TileMode ty,
- const SkMatrix* localMatrix,
- SkAlphaType outputAlphaType = kPremul_SkAlphaType);
+ static sk_sp<SkShader> Make(sk_sp<SkImage>, TileMode tx, TileMode ty,
+ const SkMatrix* localMatrix);
bool isOpaque() const override;
@@ -30,23 +27,19 @@ 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);
-private:
- SkImageShader(sk_sp<SkImage>,
- SkShader::TileMode tx,
- SkShader::TileMode ty,
- const SkMatrix* localMatrix,
- SkAlphaType outputAlphaType);
-
+protected:
void flatten(SkWriteBuffer&) const override;
Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override;
#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
- bool onIsABitmap(SkBitmap*, SkMatrix*, SkShader::TileMode*) const override;
+ bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override;
#endif
- SkImage* onIsAImage(SkMatrix*, SkShader::TileMode*) const override;
+ SkImage* onIsAImage(SkMatrix*, TileMode*) const override;
bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override;
@@ -57,12 +50,13 @@ private:
&this->getLocalMatrix());
}
- sk_sp<SkImage> fImage;
- const SkShader::TileMode fTileModeX;
- const SkShader::TileMode fTileModeY;
- const SkAlphaType fOutputAlphaType;
+ sk_sp<SkImage> fImage;
+ const TileMode fTileModeX;
+ const TileMode fTileModeY;
+private:
friend class SkShaderBase;
+
typedef SkShaderBase INHERITED;
};