aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-04-10 16:47:46 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-11 11:25:06 +0000
commit2097fd03ffea48bd904c48c93348b2350600870e (patch)
tree11fac8634429396ed18c59d1e73a8e5dde379de8 /src/shaders
parenta479f96dafa94549ed3b5b72d1d25bacd9d18b16 (diff)
Fix handling of MaskFilter matrices
1) extend GrFPArgs to track pre/post local matrices, add helpers for creating pre/post wrapper args 2) add a SkShaderBase helper (totalLocalMatrix) to centralize the LM sandwich logic. 3) update call sites to use the above 4) rename SkMatrixFilter::makeWithLocalMatrix -> makeWithMatrix, to disambiguate vs. SkShader::makeWithLocalMatrix. BUG=skia:7744 Change-Id: Ib2b7b007e6924979b00649dde7c94ef4b34771f1 Reviewed-on: https://skia-review.googlesource.com/119330 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/shaders')
-rw-r--r--src/shaders/SkImageShader.cpp14
-rw-r--r--src/shaders/SkLocalMatrixShader.cpp7
-rw-r--r--src/shaders/SkPerlinNoiseShader.cpp13
-rw-r--r--src/shaders/SkPictureShader.cpp67
-rw-r--r--src/shaders/SkPictureShader.h4
-rw-r--r--src/shaders/SkShader.cpp23
-rw-r--r--src/shaders/SkShaderBase.h14
-rw-r--r--src/shaders/gradients/SkLinearGradient.cpp9
-rw-r--r--src/shaders/gradients/SkRadialGradient.cpp11
-rw-r--r--src/shaders/gradients/SkSweepGradient.cpp9
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.cpp8
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp13
12 files changed, 88 insertions, 104 deletions
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 265f7e6013..1838e9e498 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -213,19 +213,11 @@ static GrSamplerState::WrapMode tile_mode_to_wrap_mode(const SkShader::TileMode
std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
const GrFPArgs& args) const {
- SkMatrix lm = this->getLocalMatrix();
+ const auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
SkMatrix lmInverse;
- if (!lm.invert(&lmInverse)) {
+ if (!lm->invert(&lmInverse)) {
return nullptr;
}
- if (args.fLocalMatrix) {
- SkMatrix inv;
- if (!args.fLocalMatrix->invert(&inv)) {
- return nullptr;
- }
- lmInverse.postConcat(inv);
- lm.preConcat(*args.fLocalMatrix);
- }
GrSamplerState::WrapMode wrapModes[] = {tile_mode_to_wrap_mode(fTileModeX),
tile_mode_to_wrap_mode(fTileModeY)};
@@ -236,7 +228,7 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
// are provided by the caller.
bool doBicubic;
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
- args.fFilterQuality, *args.fViewMatrix, lm,
+ args.fFilterQuality, *args.fViewMatrix, *lm,
args.fContext->contextPriv().sharpenMipmappedTextures(), &doBicubic);
GrSamplerState samplerState(wrapModes, textureFilterMode);
sk_sp<SkColorSpace> texColorSpace;
diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp
index ca99af1bef..78110f5821 100644
--- a/src/shaders/SkLocalMatrixShader.cpp
+++ b/src/shaders/SkLocalMatrixShader.cpp
@@ -15,13 +15,8 @@
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(
const GrFPArgs& args) const {
- SkMatrix tmp = this->getLocalMatrix();
- if (args.fLocalMatrix) {
- tmp.preConcat(*args.fLocalMatrix);
- }
return as_SB(fProxyShader)
- ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, &tmp,
- args.fFilterQuality, args.fDstColorSpaceInfo));
+ ->asFragmentProcessor(args.makeWithPreLocalMatrix(this->getLocalMatrix()));
}
#endif
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index 6179da3d32..8f6c85a494 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -1394,13 +1394,8 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
const GrFPArgs& args) const {
SkASSERT(args.fContext);
- SkMatrix localMatrix = this->getLocalMatrix();
- if (args.fLocalMatrix) {
- localMatrix.preConcat(*args.fLocalMatrix);
- }
-
- SkMatrix matrix = *args.fViewMatrix;
- matrix.preConcat(localMatrix);
+ const auto localMatrix = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
+ const auto matrix = SkMatrix::Concat(*args.fViewMatrix, *localMatrix);
// Either we don't stitch tiles, either we have a valid tile size
SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
@@ -1413,8 +1408,8 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
matrix);
SkMatrix m = *args.fViewMatrix;
- m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
- m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
+ m.setTranslateX(-localMatrix->getTranslateX() + SK_Scalar1);
+ m.setTranslateY(-localMatrix->getTranslateY() + SK_Scalar1);
auto proxyProvider = args.fContext->contextPriv().proxyProvider();
if (fType == kImprovedNoise_Type) {
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index 1d19b04721..de642a7dda 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -175,24 +175,20 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
//
// 1) a cached image shader, which wraps a single picture tile at the given CTM/local matrix
//
-// 2) a "composite" local matrix, to be passed down when dispatching createContext(),
+// 2) a tile scale adjustment, to be applied downstream when dispatching createContext(),
// appendStages() and asFragmentProcessor() in callers
//
// The composite local matrix includes the actual local matrix, any inherited/outer local matrix
// and a scale component (to mape the actual tile bitmap size -> fTile size).
//
sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix,
- const SkMatrix* outerLocalMatrix,
+ const SkMatrix& localMatrix,
SkColorSpace* dstColorSpace,
- SkMatrix* compositeLocalMatrix,
+ SkVector* scaleAdjust,
const int maxTextureSize) const {
SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
- *compositeLocalMatrix = this->getLocalMatrix();
- if (outerLocalMatrix) {
- compositeLocalMatrix->preConcat(*outerLocalMatrix);
- }
- const SkMatrix m = SkMatrix::Concat(viewMatrix, *compositeLocalMatrix);
+ const SkMatrix m = SkMatrix::Concat(viewMatrix, localMatrix);
// Use a rotation-invariant scale
SkPoint scale;
@@ -274,37 +270,52 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix,
fAddedToCache.store(true);
}
- compositeLocalMatrix->preScale(1 / tileScale.width(), 1 / tileScale.height());
+ scaleAdjust->set(1 / tileScale.width(), 1 / tileScale.height());
return tileShader;
}
bool SkPictureShader::onAppendStages(const StageRec& rec) const {
+ auto lm = this->totalLocalMatrix(rec.fLocalM);
+ SkVector scaleAdjust;
+
// Keep bitmapShader alive by using alloc instead of stack memory
auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>();
- SkMatrix compositeLocalMatrix;
- bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS, &compositeLocalMatrix);
+ bitmapShader = this->refBitmapShader(rec.fCTM, *lm, rec.fDstCS, &scaleAdjust);
+
+ if (!bitmapShader) {
+ return false;
+ }
+
+ if (scaleAdjust != SkVector::Make(1, 1)) {
+ lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY);
+ }
StageRec localRec = rec;
- localRec.fLocalM = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix;
+ localRec.fLocalM = lm->isIdentity() ? nullptr : &(*lm);
- return bitmapShader && as_SB(bitmapShader)->appendStages(localRec);
+ return as_SB(bitmapShader)->appendStages(localRec);
}
/////////////////////////////////////////////////////////////////////////////////////////
SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc)
const {
- SkMatrix compositeLocalMatrix;
+ auto lm = this->totalLocalMatrix(rec.fLocalMatrix);
+ SkVector scaleAdjust;
sk_sp<SkShader> bitmapShader = this->refBitmapShader(*rec.fMatrix,
- rec.fLocalMatrix,
+ *lm,
rec.fDstColorSpace,
- &compositeLocalMatrix);
+ &scaleAdjust);
if (!bitmapShader) {
return nullptr;
}
+ if (scaleAdjust != SkVector::Make(1, 1)) {
+ lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY);
+ }
+
ContextRec localRec = rec;
- localRec.fLocalMatrix = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix;
+ localRec.fLocalMatrix = lm->isIdentity() ? nullptr : &(*lm);
PictureShaderContext* ctx =
alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc);
@@ -369,20 +380,22 @@ std::unique_ptr<GrFragmentProcessor> SkPictureShader::asFragmentProcessor(
if (args.fContext) {
maxTextureSize = args.fContext->caps()->maxTextureSize();
}
- SkMatrix compositeLocalMatrix;
- sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix,
+
+ auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
+ SkVector scaleAdjust;
+ sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix,*lm,
args.fDstColorSpaceInfo->colorSpace(),
- &compositeLocalMatrix,
- maxTextureSize));
+ &scaleAdjust, maxTextureSize));
if (!bitmapShader) {
return nullptr;
}
- return as_SB(bitmapShader)->asFragmentProcessor(
- GrFPArgs(args.fContext,
- args.fViewMatrix,
- compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix,
- args.fFilterQuality,
- args.fDstColorSpaceInfo));
+ if (scaleAdjust != SkVector::Make(1, 1)) {
+ lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY);
+ }
+
+ GrFPArgs newArgs(args.fContext, args.fViewMatrix, args.fFilterQuality, args.fDstColorSpaceInfo);
+
+ return as_SB(bitmapShader)->asFragmentProcessor(newArgs.makeWithPreLocalMatrix(*lm));
}
#endif
diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h
index 4970dac81b..5f28b6074b 100644
--- a/src/shaders/SkPictureShader.h
+++ b/src/shaders/SkPictureShader.h
@@ -46,9 +46,9 @@ private:
SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*,
sk_sp<SkColorSpace>);
- sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix,
+ sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix& localMatrix,
SkColorSpace* dstColorSpace,
- SkMatrix* compositeLocalMatrix,
+ SkVector* scaleAdjust,
const int maxTextureSize = 0) const;
class PictureShaderContext : public Context {
diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp
index 265f22beaa..f3ffd26ef4 100644
--- a/src/shaders/SkShader.cpp
+++ b/src/shaders/SkShader.cpp
@@ -67,15 +67,26 @@ void SkShaderBase::flatten(SkWriteBuffer& buffer) const {
}
}
+SkTCopyOnFirstWrite<SkMatrix>
+SkShaderBase::totalLocalMatrix(const SkMatrix* preLocalMatrix,
+ const SkMatrix* postLocalMatrix) const {
+ SkTCopyOnFirstWrite<SkMatrix> m(fLocalMatrix);
+
+ if (preLocalMatrix) {
+ m.writable()->preConcat(*preLocalMatrix);
+ }
+
+ if (postLocalMatrix) {
+ m.writable()->postConcat(*postLocalMatrix);
+ }
+
+ return m;
+}
+
bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
const SkMatrix* outerLocalMatrix,
SkMatrix* totalInverse) const {
- SkMatrix total = SkMatrix::Concat(ctm, fLocalMatrix);
- if (outerLocalMatrix) {
- total.preConcat(*outerLocalMatrix);
- }
-
- return total.invert(totalInverse);
+ return SkMatrix::Concat(ctm, *this->totalLocalMatrix(outerLocalMatrix)).invert(totalInverse);
}
bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index 89674a6ebb..cddc5540ee 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -12,6 +12,7 @@
#include "SkMask.h"
#include "SkMatrix.h"
#include "SkShader.h"
+#include "SkTLazy.h"
#if SK_SUPPORT_GPU
#include "GrFPArgs.h"
@@ -185,9 +186,16 @@ public:
// If this returns false, then we draw nothing (do not fall back to shader context)
bool appendStages(const StageRec&) const;
- bool computeTotalInverse(const SkMatrix& ctm,
- const SkMatrix* outerLocalMatrix,
- SkMatrix* totalInverse) const;
+ bool SK_WARN_UNUSED_RESULT computeTotalInverse(const SkMatrix& ctm,
+ const SkMatrix* outerLocalMatrix,
+ SkMatrix* totalInverse) const;
+
+ // Returns the total local matrix for this shader:
+ //
+ // M = postLocalMatrix x shaderLocalMatrix x preLocalMatrix
+ //
+ SkTCopyOnFirstWrite<SkMatrix> totalLocalMatrix(const SkMatrix* preLocalMatrix,
+ const SkMatrix* postLocalMatrix = nullptr) const;
#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index b6436ca801..a377442dc4 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -195,16 +195,9 @@ std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
SkASSERT(args.fContext);
SkMatrix matrix;
- if (!this->getLocalMatrix().invert(&matrix)) {
+ if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
return nullptr;
}
- if (args.fLocalMatrix) {
- SkMatrix inv;
- if (!args.fLocalMatrix->invert(&inv)) {
- return nullptr;
- }
- matrix.postConcat(inv);
- }
matrix.postConcat(fPtsToUnit);
return GrLinearGradient::Make(GrGradientEffect::CreateArgs(
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index 3f71f38c1f..6d193615a4 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -162,19 +162,10 @@ void GrRadialGradient::GLSLRadialProcessor::emitCode(EmitArgs& args) {
std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
const GrFPArgs& args) const {
- SkASSERT(args.fContext);
-
SkMatrix matrix;
- if (!this->getLocalMatrix().invert(&matrix)) {
+ if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
return nullptr;
}
- if (args.fLocalMatrix) {
- SkMatrix inv;
- if (!args.fLocalMatrix->invert(&inv)) {
- return nullptr;
- }
- matrix.postConcat(inv);
- }
matrix.postConcat(fPtsToUnit);
return GrRadialGradient::Make(GrGradientEffect::CreateArgs(
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index e9c4450b00..3f605d7761 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -216,16 +216,9 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
const GrFPArgs& args) const {
SkMatrix matrix;
- if (!this->getLocalMatrix().invert(&matrix)) {
+ if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
return nullptr;
}
- if (args.fLocalMatrix) {
- SkMatrix inv;
- if (!args.fLocalMatrix->invert(&inv)) {
- return nullptr;
- }
- matrix.postConcat(inv);
- }
matrix.postConcat(fPtsToUnit);
return GrSweepGradient::Make(
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index cce25d00b7..88f0f82245 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -175,9 +175,13 @@ void SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const {
std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
const GrFPArgs& args) const {
- SkASSERT(args.fContext);
+ SkMatrix matrix;
+ if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
+ return nullptr;
+ }
+
return Gr2PtConicalGradientEffect::Make(
- GrGradientEffect::CreateArgs(args.fContext, this, args.fLocalMatrix, fTileMode,
+ GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
args.fDstColorSpaceInfo->colorSpace()));
}
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
index c242895f1c..9d447785ed 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -388,18 +388,7 @@ std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
const SkTwoPointConicalGradient& shader =
*static_cast<const SkTwoPointConicalGradient*>(args.fShader);
- SkMatrix matrix;
- if (!shader.getLocalMatrix().invert(&matrix)) {
- return nullptr;
- }
- if (args.fMatrix) {
- SkMatrix inv;
- if (!args.fMatrix->invert(&inv)) {
- return nullptr;
- }
- matrix.postConcat(inv);
- }
-
+ SkMatrix matrix = *args.fMatrix;
GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fWrapMode,
args.fDstColorSpace);
// Data and matrix has to be prepared before constructing TwoPointConicalEffect so its parent