diff --git a/gm/shadermaskfilter.cpp b/gm/shadermaskfilter.cpp index a3f4fd87b7..c1bee02e6d 100644 --- a/gm/shadermaskfilter.cpp +++ b/gm/shadermaskfilter.cpp @@ -11,7 +11,6 @@ #include "SkCanvas.h" #include "SkImage.h" #include "SkMaskFilter.h" -#include "SkPictureRecorder.h" #include "SkShaderMaskFilter.h" static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y, @@ -221,92 +220,3 @@ DEF_SIMPLE_GM(savelayer_maskfilter, canvas, 450, 675) { } } -static void draw_mask(SkCanvas* canvas) { - SkPaint p; - p.setAntiAlias(true); - canvas->drawOval(SkRect::Make(canvas->imageInfo().bounds()), p); -} - -DEF_SIMPLE_GM(shadermaskfilter_localmatrix, canvas, 1200, 800) { - static constexpr SkScalar kSize = 100; - - using ShaderMakerT = sk_sp(*)(SkCanvas*, const SkMatrix& lm); - static const ShaderMakerT gShaderMakers[] = { - [](SkCanvas* canvas, const SkMatrix& lm) -> sk_sp { - auto surface = sk_tool_utils::makeSurface(canvas, - SkImageInfo::MakeN32Premul(kSize, kSize)); - draw_mask(surface->getCanvas()); - return surface->makeImageSnapshot()->makeShader(SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, &lm); - }, - [](SkCanvas*, const SkMatrix& lm) -> sk_sp { - SkPictureRecorder recorder; - draw_mask(recorder.beginRecording(kSize, kSize)); - return SkShader::MakePictureShader(recorder.finishRecordingAsPicture(), - SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, - &lm, nullptr); - }, - }; - - struct Config { - SkMatrix fCanvasMatrix, - fMaskMatrix, - fShaderMatrix; - } gConfigs[] = { - { SkMatrix::I(), SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10) }, - { SkMatrix::MakeScale(2, 2), SkMatrix::I(), SkMatrix::MakeTrans(10, 10) }, - { SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10), SkMatrix::I() }, - { SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)), - SkMatrix::I(), SkMatrix::I() }, - { SkMatrix::I(), - SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)), - SkMatrix::I() }, - { SkMatrix::I(), SkMatrix::I(), - SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)) }, - }; - - using DrawerT = void(*)(SkCanvas*, const SkRect&, const SkPaint&); - static const DrawerT gDrawers[] = { - [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) { - canvas->drawRect(dest, mask); - }, - [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) { - canvas->saveLayer(&dest, &mask); - SkPaint p = mask; - p.setMaskFilter(nullptr); - canvas->drawPaint(p); - canvas->restore(); - }, - }; - - SkPaint paint, rectPaint; - paint.setColor(0xff00ff00); - rectPaint.setStyle(SkPaint::kStroke_Style); - rectPaint.setColor(0xffff0000); - - for (const auto& sm : gShaderMakers) { - for (const auto& drawer : gDrawers) { - { - SkAutoCanvasRestore acr(canvas, true); - for (const auto& cfg : gConfigs) { - paint.setMaskFilter(SkShaderMaskFilter::Make(sm(canvas, cfg.fShaderMatrix)) - ->makeWithMatrix(cfg.fMaskMatrix)); - auto dest = SkRect::MakeWH(kSize, kSize); - SkMatrix::Concat(cfg.fMaskMatrix, cfg.fShaderMatrix).mapRect(&dest); - - { - SkAutoCanvasRestore acr(canvas, true); - canvas->concat(cfg.fCanvasMatrix); - drawer(canvas, dest, paint); - canvas->drawRect(dest, rectPaint); - } - - canvas->translate(kSize * 2.5f, 0); - } - } - canvas->translate(0, kSize * 2.5f); - } - - } -} diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index bd2a20b825..1ea774a027 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -50,14 +50,7 @@ public: static sk_sp MakeCombine(sk_sp filterA, sk_sp filterB, SkCoverageMode mode); - /** - * Construct a maskfilter with an additional transform. - * - * Note: unlike shader local matrices, this transform composes next to the CTM. - * - * TotalMatrix = CTM x MaskFilterMatrix x (optional/downstream) ShaderLocalMatrix - */ - sk_sp makeWithMatrix(const SkMatrix&) const; + sk_sp makeWithLocalMatrix(const SkMatrix&) const; virtual void toString(SkString* str) const = 0; SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter) diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 26cdc39313..5f84ba1aec 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -487,7 +487,7 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain // todo: can we unify with similar adjustment in SkGpuDevice? SkTCopyOnFirstWrite paint(origPaint); if (paint->getMaskFilter()) { - paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithMatrix(this->ctm())); + paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm())); } this->drawSprite(static_cast(device)->fBitmap, x, y, *paint); } @@ -546,7 +546,7 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain } if (paint->getMaskFilter()) { - paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithMatrix(this->ctm())); + paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm())); } if (!clipImage) { diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index 8e555f37ad..e1805637a9 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -635,9 +635,9 @@ void SkCombineMF::toString(SkString* str) const { /////////////////////////////////////////////////////////////////////////////////////////////////// -class SkMatrixMF : public SkMaskFilterBase { +class SkLocalMatrixMF : public SkMaskFilterBase { public: - SkMatrixMF(sk_sp filter, const SkMatrix& lm) + SkLocalMatrixMF(sk_sp filter, const SkMatrix& lm) : fFilter(std::move(filter)) , fLM(lm) {} @@ -657,7 +657,7 @@ public: SkMask::Format getFormat() const override { return as_MFB(fFilter)->getFormat(); } void toString(SkString* str) const override { - str->set("SkMatrixMF:"); + str->set("SkLocalMatrixMF:"); } SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixMF) @@ -665,7 +665,16 @@ public: protected: #if SK_SUPPORT_GPU std::unique_ptr onAsFragmentProcessor(const GrFPArgs& args) const override{ - return as_MFB(fFilter)->asFragmentProcessor(args.makeWithPostLocalMatrix(fLM)); + GrFPArgs newArgs = args; + + SkMatrix storage; + if (args.fLocalMatrix) { + storage.setConcat(*args.fLocalMatrix, fLM); + newArgs.fLocalMatrix = &storage; + } else { + newArgs.fLocalMatrix = &fLM; + } + return as_MFB(fFilter)->asFragmentProcessor(newArgs); } bool onHasFragmentProcessor() const override { @@ -686,11 +695,11 @@ private: typedef SkMaskFilterBase INHERITED; }; -sk_sp SkMatrixMF::CreateProc(SkReadBuffer& buffer) { - SkMatrix m; - buffer.readMatrix(&m); +sk_sp SkLocalMatrixMF::CreateProc(SkReadBuffer& buffer) { + SkMatrix lm; + buffer.readMatrix(&lm); auto filter = buffer.readMaskFilter(); - return filter ? filter->makeWithMatrix(m) : nullptr; + return filter ? filter->makeWithLocalMatrix(lm) : nullptr; } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -726,16 +735,16 @@ sk_sp SkMaskFilter::MakeCombine(sk_sp dst, sk_sp(new SkCombineMF(std::move(dst), std::move(src), mode)); } -sk_sp SkMaskFilter::makeWithMatrix(const SkMatrix& lm) const { +sk_sp SkMaskFilter::makeWithLocalMatrix(const SkMatrix& lm) const { sk_sp me = sk_ref_sp(const_cast(this)); if (lm.isIdentity()) { return me; } - return sk_sp(new SkMatrixMF(std::move(me), lm)); + return sk_sp(new SkLocalMatrixMF(std::move(me), lm)); } void SkMaskFilter::InitializeFlattenables() { - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixMF) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLocalMatrixMF) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeMF) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCombineMF) sk_register_blur_maskfilter_createproc(); diff --git a/src/gpu/GrFPArgs.h b/src/gpu/GrFPArgs.h index 3c1b8e37b9..cdb2e5de50 100644 --- a/src/gpu/GrFPArgs.h +++ b/src/gpu/GrFPArgs.h @@ -9,84 +9,39 @@ #define GrFPArgs_DEFINED #include "SkFilterQuality.h" -#include "SkMatrix.h" +class SkMatrix; class GrContext; class GrColorSpaceInfo; struct GrFPArgs { + GrFPArgs(GrContext* context, + const SkMatrix* viewMatrix, + const SkMatrix* localMatrix, + SkFilterQuality filterQuality, + const GrColorSpaceInfo* dstColorSpaceInfo) + : fContext(context) + , fViewMatrix(viewMatrix) + , fLocalMatrix(localMatrix) + , fFilterQuality(filterQuality) + , fDstColorSpaceInfo(dstColorSpaceInfo) {} + GrFPArgs(GrContext* context, const SkMatrix* viewMatrix, SkFilterQuality filterQuality, const GrColorSpaceInfo* dstColorSpaceInfo) : fContext(context) , fViewMatrix(viewMatrix) + , fLocalMatrix(nullptr) , fFilterQuality(filterQuality) - , fDstColorSpaceInfo(dstColorSpaceInfo) { - SkASSERT(fContext); - SkASSERT(fViewMatrix); - } - - class WithMatrixStorage; - - WithMatrixStorage makeWithPreLocalMatrix(const SkMatrix&) const; - WithMatrixStorage makeWithPostLocalMatrix(const SkMatrix&) const; + , fDstColorSpaceInfo(dstColorSpaceInfo) {} GrContext* fContext; const SkMatrix* fViewMatrix; - - // We track both pre and post local matrix adjustments. For a given FP: - // - // total_local_matrix = postLocalMatrix x FP_localMatrix x preLocalMatrix - // - // Use the helpers above to create pre/post GrFPArgs wrappers. - // - const SkMatrix* fPreLocalMatrix = nullptr; - const SkMatrix* fPostLocalMatrix = nullptr; - + const SkMatrix* fLocalMatrix; SkFilterQuality fFilterQuality; const GrColorSpaceInfo* fDstColorSpaceInfo; }; -class GrFPArgs::WithMatrixStorage final : public GrFPArgs { -private: - explicit WithMatrixStorage(const GrFPArgs& args) : INHERITED(args) {} - - friend struct GrFPArgs; - SkMatrix fStorage; - - using INHERITED = GrFPArgs; -}; - -inline GrFPArgs::WithMatrixStorage GrFPArgs::makeWithPreLocalMatrix(const SkMatrix& lm) const { - WithMatrixStorage newArgs(*this); - - if (!lm.isIdentity()) { - if (fPreLocalMatrix) { - newArgs.fStorage.setConcat(lm, *fPreLocalMatrix); - newArgs.fPreLocalMatrix = newArgs.fStorage.isIdentity() ? nullptr : &newArgs.fStorage; - } else { - newArgs.fPreLocalMatrix = &lm; - } - } - - return newArgs; -} - -inline GrFPArgs::WithMatrixStorage GrFPArgs::makeWithPostLocalMatrix(const SkMatrix& lm) const { - WithMatrixStorage newArgs(*this); - - if (!lm.isIdentity()) { - if (fPostLocalMatrix) { - newArgs.fStorage.setConcat(*fPostLocalMatrix, lm); - newArgs.fPostLocalMatrix = newArgs.fStorage.isIdentity() ? nullptr : &newArgs.fStorage; - } else { - newArgs.fPostLocalMatrix = &lm; - } - } - - return newArgs; -} - #endif diff --git a/src/gpu/GrTestUtils.cpp b/src/gpu/GrTestUtils.cpp index 2aff35dad2..8958f84704 100644 --- a/src/gpu/GrTestUtils.cpp +++ b/src/gpu/GrTestUtils.cpp @@ -337,7 +337,8 @@ TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d) : fViewMatrixStorage(TestMatrix(d->fRandom)) , fColorSpaceInfoStorage(skstd::make_unique(TestColorSpace(d->fRandom), kRGBA_8888_GrPixelConfig)) - , fArgs(d->context(), &fViewMatrixStorage, kNone_SkFilterQuality, fColorSpaceInfoStorage.get()) + , fArgs(d->context(), &fViewMatrixStorage, nullptr, kNone_SkFilterQuality, + fColorSpaceInfoStorage.get()) {} TestAsFPArgs::~TestAsFPArgs() {} diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index fca372eabd..eb26ba2f9b 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1092,7 +1092,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const if (tmpUnfiltered.getMaskFilter()) { SkMatrix ctm = this->ctm(); ctm.postTranslate(-SkIntToScalar(left + offset.fX), -SkIntToScalar(top + offset.fY)); - tmpUnfiltered.setMaskFilter(tmpUnfiltered.getMaskFilter()->makeWithMatrix(ctm)); + tmpUnfiltered.setMaskFilter(tmpUnfiltered.getMaskFilter()->makeWithLocalMatrix(ctm)); } tmpUnfiltered.setImageFilter(nullptr); diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 99465f620b..b4cb22bd10 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -514,7 +514,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context, if (textureIsAlphaOnly) { if (const auto* shader = as_SB(paint.getShader())) { shaderFP = shader->asFragmentProcessor(GrFPArgs( - context, &viewM, paint.getFilterQuality(), &colorSpaceInfo)); + context, &viewM, nullptr, paint.getFilterQuality(), &colorSpaceInfo)); if (!shaderFP) { return false; } diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp index 1838e9e498..265f7e6013 100644 --- a/src/shaders/SkImageShader.cpp +++ b/src/shaders/SkImageShader.cpp @@ -213,11 +213,19 @@ static GrSamplerState::WrapMode tile_mode_to_wrap_mode(const SkShader::TileMode std::unique_ptr SkImageShader::asFragmentProcessor( const GrFPArgs& args) const { - const auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); + SkMatrix lm = this->getLocalMatrix(); 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)}; @@ -228,7 +236,7 @@ std::unique_ptr 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 texColorSpace; diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp index 78110f5821..ca99af1bef 100644 --- a/src/shaders/SkLocalMatrixShader.cpp +++ b/src/shaders/SkLocalMatrixShader.cpp @@ -15,8 +15,13 @@ #if SK_SUPPORT_GPU std::unique_ptr SkLocalMatrixShader::asFragmentProcessor( const GrFPArgs& args) const { + SkMatrix tmp = this->getLocalMatrix(); + if (args.fLocalMatrix) { + tmp.preConcat(*args.fLocalMatrix); + } return as_SB(fProxyShader) - ->asFragmentProcessor(args.makeWithPreLocalMatrix(this->getLocalMatrix())); + ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, &tmp, + args.fFilterQuality, args.fDstColorSpaceInfo)); } #endif diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp index 8f6c85a494..6179da3d32 100644 --- a/src/shaders/SkPerlinNoiseShader.cpp +++ b/src/shaders/SkPerlinNoiseShader.cpp @@ -1394,8 +1394,13 @@ std::unique_ptr SkPerlinNoiseShaderImpl::asFragmentProcesso const GrFPArgs& args) const { SkASSERT(args.fContext); - const auto localMatrix = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); - const auto matrix = SkMatrix::Concat(*args.fViewMatrix, *localMatrix); + SkMatrix localMatrix = this->getLocalMatrix(); + if (args.fLocalMatrix) { + localMatrix.preConcat(*args.fLocalMatrix); + } + + SkMatrix matrix = *args.fViewMatrix; + matrix.preConcat(localMatrix); // Either we don't stitch tiles, either we have a valid tile size SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); @@ -1408,8 +1413,8 @@ std::unique_ptr 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 de642a7dda..1d19b04721 100644 --- a/src/shaders/SkPictureShader.cpp +++ b/src/shaders/SkPictureShader.cpp @@ -175,20 +175,24 @@ 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 tile scale adjustment, to be applied downstream when dispatching createContext(), +// 2) a "composite" local matrix, to be passed down 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 SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, - const SkMatrix& localMatrix, + const SkMatrix* outerLocalMatrix, SkColorSpace* dstColorSpace, - SkVector* scaleAdjust, + SkMatrix* compositeLocalMatrix, const int maxTextureSize) const { SkASSERT(fPicture && !fPicture->cullRect().isEmpty()); - const SkMatrix m = SkMatrix::Concat(viewMatrix, localMatrix); + *compositeLocalMatrix = this->getLocalMatrix(); + if (outerLocalMatrix) { + compositeLocalMatrix->preConcat(*outerLocalMatrix); + } + const SkMatrix m = SkMatrix::Concat(viewMatrix, *compositeLocalMatrix); // Use a rotation-invariant scale SkPoint scale; @@ -270,52 +274,37 @@ sk_sp SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, fAddedToCache.store(true); } - scaleAdjust->set(1 / tileScale.width(), 1 / tileScale.height()); + compositeLocalMatrix->preScale(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>(); - 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); - } + SkMatrix compositeLocalMatrix; + bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS, &compositeLocalMatrix); StageRec localRec = rec; - localRec.fLocalM = lm->isIdentity() ? nullptr : &(*lm); + localRec.fLocalM = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix; - return as_SB(bitmapShader)->appendStages(localRec); + return bitmapShader && as_SB(bitmapShader)->appendStages(localRec); } ///////////////////////////////////////////////////////////////////////////////////////// SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { - auto lm = this->totalLocalMatrix(rec.fLocalMatrix); - SkVector scaleAdjust; + SkMatrix compositeLocalMatrix; sk_sp bitmapShader = this->refBitmapShader(*rec.fMatrix, - *lm, + rec.fLocalMatrix, rec.fDstColorSpace, - &scaleAdjust); + &compositeLocalMatrix); if (!bitmapShader) { return nullptr; } - if (scaleAdjust != SkVector::Make(1, 1)) { - lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY); - } - ContextRec localRec = rec; - localRec.fLocalMatrix = lm->isIdentity() ? nullptr : &(*lm); + localRec.fLocalMatrix = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix; PictureShaderContext* ctx = alloc->make(*this, localRec, std::move(bitmapShader), alloc); @@ -380,22 +369,20 @@ std::unique_ptr SkPictureShader::asFragmentProcessor( if (args.fContext) { maxTextureSize = args.fContext->caps()->maxTextureSize(); } - - auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); - SkVector scaleAdjust; - sk_sp bitmapShader(this->refBitmapShader(*args.fViewMatrix,*lm, + SkMatrix compositeLocalMatrix; + sk_sp bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix, args.fDstColorSpaceInfo->colorSpace(), - &scaleAdjust, maxTextureSize)); + &compositeLocalMatrix, + maxTextureSize)); if (!bitmapShader) { return nullptr; } - 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)); + return as_SB(bitmapShader)->asFragmentProcessor( + GrFPArgs(args.fContext, + args.fViewMatrix, + compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix, + args.fFilterQuality, + args.fDstColorSpaceInfo)); } #endif diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h index 5f28b6074b..4970dac81b 100644 --- a/src/shaders/SkPictureShader.h +++ b/src/shaders/SkPictureShader.h @@ -46,9 +46,9 @@ private: SkPictureShader(sk_sp, TileMode, TileMode, const SkMatrix*, const SkRect*, sk_sp); - sk_sp refBitmapShader(const SkMatrix&, const SkMatrix& localMatrix, + sk_sp refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix, SkColorSpace* dstColorSpace, - SkVector* scaleAdjust, + SkMatrix* compositeLocalMatrix, const int maxTextureSize = 0) const; class PictureShaderContext : public Context { diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp index f3ffd26ef4..265f22beaa 100644 --- a/src/shaders/SkShader.cpp +++ b/src/shaders/SkShader.cpp @@ -67,26 +67,15 @@ void SkShaderBase::flatten(SkWriteBuffer& buffer) const { } } -SkTCopyOnFirstWrite -SkShaderBase::totalLocalMatrix(const SkMatrix* preLocalMatrix, - const SkMatrix* postLocalMatrix) const { - SkTCopyOnFirstWrite 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 { - return SkMatrix::Concat(ctm, *this->totalLocalMatrix(outerLocalMatrix)).invert(totalInverse); + SkMatrix total = SkMatrix::Concat(ctm, fLocalMatrix); + if (outerLocalMatrix) { + total.preConcat(*outerLocalMatrix); + } + + return total.invert(totalInverse); } bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const { diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h index cddc5540ee..89674a6ebb 100644 --- a/src/shaders/SkShaderBase.h +++ b/src/shaders/SkShaderBase.h @@ -12,7 +12,6 @@ #include "SkMask.h" #include "SkMatrix.h" #include "SkShader.h" -#include "SkTLazy.h" #if SK_SUPPORT_GPU #include "GrFPArgs.h" @@ -186,16 +185,9 @@ public: // If this returns false, then we draw nothing (do not fall back to shader context) bool appendStages(const StageRec&) 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 totalLocalMatrix(const SkMatrix* preLocalMatrix, - const SkMatrix* postLocalMatrix = nullptr) const; + bool computeTotalInverse(const SkMatrix& ctm, + const SkMatrix* outerLocalMatrix, + SkMatrix* totalInverse) 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 a377442dc4..b6436ca801 100644 --- a/src/shaders/gradients/SkLinearGradient.cpp +++ b/src/shaders/gradients/SkLinearGradient.cpp @@ -195,9 +195,16 @@ std::unique_ptr SkLinearGradient::asFragmentProcessor( SkASSERT(args.fContext); SkMatrix matrix; - if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { + if (!this->getLocalMatrix().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 6d193615a4..3f71f38c1f 100644 --- a/src/shaders/gradients/SkRadialGradient.cpp +++ b/src/shaders/gradients/SkRadialGradient.cpp @@ -162,10 +162,19 @@ void GrRadialGradient::GLSLRadialProcessor::emitCode(EmitArgs& args) { std::unique_ptr SkRadialGradient::asFragmentProcessor( const GrFPArgs& args) const { + SkASSERT(args.fContext); + SkMatrix matrix; - if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { + if (!this->getLocalMatrix().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 3f605d7761..e9c4450b00 100644 --- a/src/shaders/gradients/SkSweepGradient.cpp +++ b/src/shaders/gradients/SkSweepGradient.cpp @@ -216,9 +216,16 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) { std::unique_ptr SkSweepGradient::asFragmentProcessor( const GrFPArgs& args) const { SkMatrix matrix; - if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { + if (!this->getLocalMatrix().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 88f0f82245..cce25d00b7 100644 --- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp +++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp @@ -175,13 +175,9 @@ void SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const { std::unique_ptr SkTwoPointConicalGradient::asFragmentProcessor( const GrFPArgs& args) const { - SkMatrix matrix; - if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { - return nullptr; - } - + SkASSERT(args.fContext); return Gr2PtConicalGradientEffect::Make( - GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode, + GrGradientEffect::CreateArgs(args.fContext, this, args.fLocalMatrix, fTileMode, args.fDstColorSpaceInfo->colorSpace())); } diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp index 9d447785ed..c242895f1c 100644 --- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp +++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp @@ -388,7 +388,18 @@ std::unique_ptr Gr2PtConicalGradientEffect::Make( const SkTwoPointConicalGradient& shader = *static_cast(args.fShader); - SkMatrix matrix = *args.fMatrix; + SkMatrix matrix; + if (!shader.getLocalMatrix().invert(&matrix)) { + return nullptr; + } + if (args.fMatrix) { + SkMatrix inv; + if (!args.fMatrix->invert(&inv)) { + return nullptr; + } + matrix.postConcat(inv); + } + 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 diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp index 0ff0af71e0..8fefc9b56e 100644 --- a/tests/TessellatingPathRendererTests.cpp +++ b/tests/TessellatingPathRendererTests.cpp @@ -479,7 +479,8 @@ static std::unique_ptr create_linear_gradient_processor(GrC sk_sp shader = SkGradientShader::MakeLinear( pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); GrColorSpaceInfo colorSpaceInfo(nullptr, kRGBA_8888_GrPixelConfig); - GrFPArgs args(ctx, &SkMatrix::I(), SkFilterQuality::kLow_SkFilterQuality, &colorSpaceInfo); + GrFPArgs args(ctx, &SkMatrix::I(), &SkMatrix::I(), SkFilterQuality::kLow_SkFilterQuality, + &colorSpaceInfo); return as_SB(shader)->asFragmentProcessor(args); }