Revert "Fix handling of MaskFilter matrices"

This reverts commit 2097fd03ff.

Reason for revert: This is breaking a lot of Windows bots (esp. on the shadermaskfilter_localmatrix)

Original change's description:
> 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>

TBR=bsalomon@google.com,robertphillips@google.com,fmalita@chromium.org,reed@google.com

Change-Id: I918dbb95bf00b3122e6699b84566ec82dbb5fc5c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7744
Reviewed-on: https://skia-review.googlesource.com/120340
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2018-04-11 12:38:41 +00:00 committed by Skia Commit-Bot
parent 90f09e7853
commit c64ee20e13
21 changed files with 148 additions and 263 deletions

View File

@ -11,7 +11,6 @@
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkImage.h" #include "SkImage.h"
#include "SkMaskFilter.h" #include "SkMaskFilter.h"
#include "SkPictureRecorder.h"
#include "SkShaderMaskFilter.h" #include "SkShaderMaskFilter.h"
static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y, 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<SkShader>(*)(SkCanvas*, const SkMatrix& lm);
static const ShaderMakerT gShaderMakers[] = {
[](SkCanvas* canvas, const SkMatrix& lm) -> sk_sp<SkShader> {
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<SkShader> {
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);
}
}
}

View File

@ -50,14 +50,7 @@ public:
static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB, static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB,
SkCoverageMode mode); SkCoverageMode mode);
/** sk_sp<SkMaskFilter> makeWithLocalMatrix(const SkMatrix&) const;
* 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<SkMaskFilter> makeWithMatrix(const SkMatrix&) const;
virtual void toString(SkString* str) const = 0; virtual void toString(SkString* str) const = 0;
SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter) SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)

View File

@ -487,7 +487,7 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
// todo: can we unify with similar adjustment in SkGpuDevice? // todo: can we unify with similar adjustment in SkGpuDevice?
SkTCopyOnFirstWrite<SkPaint> paint(origPaint); SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
if (paint->getMaskFilter()) { if (paint->getMaskFilter()) {
paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithMatrix(this->ctm())); paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
} }
this->drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint); this->drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint);
} }
@ -546,7 +546,7 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
} }
if (paint->getMaskFilter()) { if (paint->getMaskFilter()) {
paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithMatrix(this->ctm())); paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
} }
if (!clipImage) { if (!clipImage) {

View File

@ -635,9 +635,9 @@ void SkCombineMF::toString(SkString* str) const {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
class SkMatrixMF : public SkMaskFilterBase { class SkLocalMatrixMF : public SkMaskFilterBase {
public: public:
SkMatrixMF(sk_sp<SkMaskFilter> filter, const SkMatrix& lm) SkLocalMatrixMF(sk_sp<SkMaskFilter> filter, const SkMatrix& lm)
: fFilter(std::move(filter)) : fFilter(std::move(filter))
, fLM(lm) , fLM(lm)
{} {}
@ -657,7 +657,7 @@ public:
SkMask::Format getFormat() const override { return as_MFB(fFilter)->getFormat(); } SkMask::Format getFormat() const override { return as_MFB(fFilter)->getFormat(); }
void toString(SkString* str) const override { void toString(SkString* str) const override {
str->set("SkMatrixMF:"); str->set("SkLocalMatrixMF:");
} }
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixMF) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixMF)
@ -665,7 +665,16 @@ public:
protected: protected:
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{ std::unique_ptr<GrFragmentProcessor> 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 { bool onHasFragmentProcessor() const override {
@ -686,11 +695,11 @@ private:
typedef SkMaskFilterBase INHERITED; typedef SkMaskFilterBase INHERITED;
}; };
sk_sp<SkFlattenable> SkMatrixMF::CreateProc(SkReadBuffer& buffer) { sk_sp<SkFlattenable> SkLocalMatrixMF::CreateProc(SkReadBuffer& buffer) {
SkMatrix m; SkMatrix lm;
buffer.readMatrix(&m); buffer.readMatrix(&lm);
auto filter = buffer.readMaskFilter(); auto filter = buffer.readMaskFilter();
return filter ? filter->makeWithMatrix(m) : nullptr; return filter ? filter->makeWithLocalMatrix(lm) : nullptr;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -726,16 +735,16 @@ sk_sp<SkMaskFilter> SkMaskFilter::MakeCombine(sk_sp<SkMaskFilter> dst, sk_sp<SkM
return sk_sp<SkMaskFilter>(new SkCombineMF(std::move(dst), std::move(src), mode)); return sk_sp<SkMaskFilter>(new SkCombineMF(std::move(dst), std::move(src), mode));
} }
sk_sp<SkMaskFilter> SkMaskFilter::makeWithMatrix(const SkMatrix& lm) const { sk_sp<SkMaskFilter> SkMaskFilter::makeWithLocalMatrix(const SkMatrix& lm) const {
sk_sp<SkMaskFilter> me = sk_ref_sp(const_cast<SkMaskFilter*>(this)); sk_sp<SkMaskFilter> me = sk_ref_sp(const_cast<SkMaskFilter*>(this));
if (lm.isIdentity()) { if (lm.isIdentity()) {
return me; return me;
} }
return sk_sp<SkMaskFilter>(new SkMatrixMF(std::move(me), lm)); return sk_sp<SkMaskFilter>(new SkLocalMatrixMF(std::move(me), lm));
} }
void SkMaskFilter::InitializeFlattenables() { 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(SkComposeMF)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCombineMF) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCombineMF)
sk_register_blur_maskfilter_createproc(); sk_register_blur_maskfilter_createproc();

View File

@ -9,84 +9,39 @@
#define GrFPArgs_DEFINED #define GrFPArgs_DEFINED
#include "SkFilterQuality.h" #include "SkFilterQuality.h"
#include "SkMatrix.h"
class SkMatrix;
class GrContext; class GrContext;
class GrColorSpaceInfo; class GrColorSpaceInfo;
struct GrFPArgs { 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, GrFPArgs(GrContext* context,
const SkMatrix* viewMatrix, const SkMatrix* viewMatrix,
SkFilterQuality filterQuality, SkFilterQuality filterQuality,
const GrColorSpaceInfo* dstColorSpaceInfo) const GrColorSpaceInfo* dstColorSpaceInfo)
: fContext(context) : fContext(context)
, fViewMatrix(viewMatrix) , fViewMatrix(viewMatrix)
, fLocalMatrix(nullptr)
, fFilterQuality(filterQuality) , fFilterQuality(filterQuality)
, fDstColorSpaceInfo(dstColorSpaceInfo) { , fDstColorSpaceInfo(dstColorSpaceInfo) {}
SkASSERT(fContext);
SkASSERT(fViewMatrix);
}
class WithMatrixStorage;
WithMatrixStorage makeWithPreLocalMatrix(const SkMatrix&) const;
WithMatrixStorage makeWithPostLocalMatrix(const SkMatrix&) const;
GrContext* fContext; GrContext* fContext;
const SkMatrix* fViewMatrix; const SkMatrix* fViewMatrix;
const SkMatrix* fLocalMatrix;
// 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;
SkFilterQuality fFilterQuality; SkFilterQuality fFilterQuality;
const GrColorSpaceInfo* fDstColorSpaceInfo; 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 #endif

View File

@ -337,7 +337,8 @@ TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d)
: fViewMatrixStorage(TestMatrix(d->fRandom)) : fViewMatrixStorage(TestMatrix(d->fRandom))
, fColorSpaceInfoStorage(skstd::make_unique<GrColorSpaceInfo>(TestColorSpace(d->fRandom), , fColorSpaceInfoStorage(skstd::make_unique<GrColorSpaceInfo>(TestColorSpace(d->fRandom),
kRGBA_8888_GrPixelConfig)) kRGBA_8888_GrPixelConfig))
, fArgs(d->context(), &fViewMatrixStorage, kNone_SkFilterQuality, fColorSpaceInfoStorage.get()) , fArgs(d->context(), &fViewMatrixStorage, nullptr, kNone_SkFilterQuality,
fColorSpaceInfoStorage.get())
{} {}
TestAsFPArgs::~TestAsFPArgs() {} TestAsFPArgs::~TestAsFPArgs() {}

View File

@ -1092,7 +1092,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const
if (tmpUnfiltered.getMaskFilter()) { if (tmpUnfiltered.getMaskFilter()) {
SkMatrix ctm = this->ctm(); SkMatrix ctm = this->ctm();
ctm.postTranslate(-SkIntToScalar(left + offset.fX), -SkIntToScalar(top + offset.fY)); 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); tmpUnfiltered.setImageFilter(nullptr);

View File

@ -514,7 +514,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
if (textureIsAlphaOnly) { if (textureIsAlphaOnly) {
if (const auto* shader = as_SB(paint.getShader())) { if (const auto* shader = as_SB(paint.getShader())) {
shaderFP = shader->asFragmentProcessor(GrFPArgs( shaderFP = shader->asFragmentProcessor(GrFPArgs(
context, &viewM, paint.getFilterQuality(), &colorSpaceInfo)); context, &viewM, nullptr, paint.getFilterQuality(), &colorSpaceInfo));
if (!shaderFP) { if (!shaderFP) {
return false; return false;
} }

View File

@ -213,11 +213,19 @@ static GrSamplerState::WrapMode tile_mode_to_wrap_mode(const SkShader::TileMode
std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor( std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
const GrFPArgs& args) const { const GrFPArgs& args) const {
const auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); SkMatrix lm = this->getLocalMatrix();
SkMatrix lmInverse; SkMatrix lmInverse;
if (!lm->invert(&lmInverse)) { if (!lm.invert(&lmInverse)) {
return nullptr; 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), GrSamplerState::WrapMode wrapModes[] = {tile_mode_to_wrap_mode(fTileModeX),
tile_mode_to_wrap_mode(fTileModeY)}; tile_mode_to_wrap_mode(fTileModeY)};
@ -228,7 +236,7 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
// are provided by the caller. // are provided by the caller.
bool doBicubic; bool doBicubic;
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode( GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
args.fFilterQuality, *args.fViewMatrix, *lm, args.fFilterQuality, *args.fViewMatrix, lm,
args.fContext->contextPriv().sharpenMipmappedTextures(), &doBicubic); args.fContext->contextPriv().sharpenMipmappedTextures(), &doBicubic);
GrSamplerState samplerState(wrapModes, textureFilterMode); GrSamplerState samplerState(wrapModes, textureFilterMode);
sk_sp<SkColorSpace> texColorSpace; sk_sp<SkColorSpace> texColorSpace;

View File

@ -15,8 +15,13 @@
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor( std::unique_ptr<GrFragmentProcessor> SkLocalMatrixShader::asFragmentProcessor(
const GrFPArgs& args) const { const GrFPArgs& args) const {
SkMatrix tmp = this->getLocalMatrix();
if (args.fLocalMatrix) {
tmp.preConcat(*args.fLocalMatrix);
}
return as_SB(fProxyShader) return as_SB(fProxyShader)
->asFragmentProcessor(args.makeWithPreLocalMatrix(this->getLocalMatrix())); ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, &tmp,
args.fFilterQuality, args.fDstColorSpaceInfo));
} }
#endif #endif

View File

@ -1394,8 +1394,13 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
const GrFPArgs& args) const { const GrFPArgs& args) const {
SkASSERT(args.fContext); SkASSERT(args.fContext);
const auto localMatrix = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); SkMatrix localMatrix = this->getLocalMatrix();
const auto matrix = SkMatrix::Concat(*args.fViewMatrix, *localMatrix); 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 // Either we don't stitch tiles, either we have a valid tile size
SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
@ -1408,8 +1413,8 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
matrix); matrix);
SkMatrix m = *args.fViewMatrix; SkMatrix m = *args.fViewMatrix;
m.setTranslateX(-localMatrix->getTranslateX() + SK_Scalar1); m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
m.setTranslateY(-localMatrix->getTranslateY() + SK_Scalar1); m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
auto proxyProvider = args.fContext->contextPriv().proxyProvider(); auto proxyProvider = args.fContext->contextPriv().proxyProvider();
if (fType == kImprovedNoise_Type) { if (fType == kImprovedNoise_Type) {

View File

@ -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 // 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 // appendStages() and asFragmentProcessor() in callers
// //
// The composite local matrix includes the actual local matrix, any inherited/outer local matrix // 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). // and a scale component (to mape the actual tile bitmap size -> fTile size).
// //
sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix,
const SkMatrix& localMatrix, const SkMatrix* outerLocalMatrix,
SkColorSpace* dstColorSpace, SkColorSpace* dstColorSpace,
SkVector* scaleAdjust, SkMatrix* compositeLocalMatrix,
const int maxTextureSize) const { const int maxTextureSize) const {
SkASSERT(fPicture && !fPicture->cullRect().isEmpty()); 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 // Use a rotation-invariant scale
SkPoint scale; SkPoint scale;
@ -270,52 +274,37 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix,
fAddedToCache.store(true); fAddedToCache.store(true);
} }
scaleAdjust->set(1 / tileScale.width(), 1 / tileScale.height()); compositeLocalMatrix->preScale(1 / tileScale.width(), 1 / tileScale.height());
return tileShader; return tileShader;
} }
bool SkPictureShader::onAppendStages(const StageRec& rec) const { 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 // Keep bitmapShader alive by using alloc instead of stack memory
auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>(); auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>();
bitmapShader = this->refBitmapShader(rec.fCTM, *lm, rec.fDstCS, &scaleAdjust); SkMatrix compositeLocalMatrix;
bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS, &compositeLocalMatrix);
if (!bitmapShader) {
return false;
}
if (scaleAdjust != SkVector::Make(1, 1)) {
lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY);
}
StageRec localRec = rec; 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) SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc)
const { const {
auto lm = this->totalLocalMatrix(rec.fLocalMatrix); SkMatrix compositeLocalMatrix;
SkVector scaleAdjust;
sk_sp<SkShader> bitmapShader = this->refBitmapShader(*rec.fMatrix, sk_sp<SkShader> bitmapShader = this->refBitmapShader(*rec.fMatrix,
*lm, rec.fLocalMatrix,
rec.fDstColorSpace, rec.fDstColorSpace,
&scaleAdjust); &compositeLocalMatrix);
if (!bitmapShader) { if (!bitmapShader) {
return nullptr; return nullptr;
} }
if (scaleAdjust != SkVector::Make(1, 1)) {
lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY);
}
ContextRec localRec = rec; ContextRec localRec = rec;
localRec.fLocalMatrix = lm->isIdentity() ? nullptr : &(*lm); localRec.fLocalMatrix = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix;
PictureShaderContext* ctx = PictureShaderContext* ctx =
alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc); alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc);
@ -380,22 +369,20 @@ std::unique_ptr<GrFragmentProcessor> SkPictureShader::asFragmentProcessor(
if (args.fContext) { if (args.fContext) {
maxTextureSize = args.fContext->caps()->maxTextureSize(); maxTextureSize = args.fContext->caps()->maxTextureSize();
} }
SkMatrix compositeLocalMatrix;
auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix); sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, args.fLocalMatrix,
SkVector scaleAdjust;
sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix,*lm,
args.fDstColorSpaceInfo->colorSpace(), args.fDstColorSpaceInfo->colorSpace(),
&scaleAdjust, maxTextureSize)); &compositeLocalMatrix,
maxTextureSize));
if (!bitmapShader) { if (!bitmapShader) {
return nullptr; return nullptr;
} }
if (scaleAdjust != SkVector::Make(1, 1)) { return as_SB(bitmapShader)->asFragmentProcessor(
lm.writable()->preScale(scaleAdjust.fX, scaleAdjust.fY); GrFPArgs(args.fContext,
} args.fViewMatrix,
compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix,
GrFPArgs newArgs(args.fContext, args.fViewMatrix, args.fFilterQuality, args.fDstColorSpaceInfo); args.fFilterQuality,
args.fDstColorSpaceInfo));
return as_SB(bitmapShader)->asFragmentProcessor(newArgs.makeWithPreLocalMatrix(*lm));
} }
#endif #endif

View File

@ -46,9 +46,9 @@ private:
SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*, SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*,
sk_sp<SkColorSpace>); sk_sp<SkColorSpace>);
sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix& localMatrix, sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix,
SkColorSpace* dstColorSpace, SkColorSpace* dstColorSpace,
SkVector* scaleAdjust, SkMatrix* compositeLocalMatrix,
const int maxTextureSize = 0) const; const int maxTextureSize = 0) const;
class PictureShaderContext : public Context { class PictureShaderContext : public Context {

View File

@ -67,26 +67,15 @@ 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, bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
const SkMatrix* outerLocalMatrix, const SkMatrix* outerLocalMatrix,
SkMatrix* totalInverse) const { 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 { bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {

View File

@ -12,7 +12,6 @@
#include "SkMask.h" #include "SkMask.h"
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkShader.h" #include "SkShader.h"
#include "SkTLazy.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrFPArgs.h" #include "GrFPArgs.h"
@ -186,16 +185,9 @@ public:
// If this returns false, then we draw nothing (do not fall back to shader context) // If this returns false, then we draw nothing (do not fall back to shader context)
bool appendStages(const StageRec&) const; bool appendStages(const StageRec&) const;
bool SK_WARN_UNUSED_RESULT computeTotalInverse(const SkMatrix& ctm, bool computeTotalInverse(const SkMatrix& ctm,
const SkMatrix* outerLocalMatrix, const SkMatrix* outerLocalMatrix,
SkMatrix* totalInverse) const; 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 #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const { virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {

View File

@ -195,9 +195,16 @@ std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
SkASSERT(args.fContext); SkASSERT(args.fContext);
SkMatrix matrix; SkMatrix matrix;
if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { if (!this->getLocalMatrix().invert(&matrix)) {
return nullptr; return nullptr;
} }
if (args.fLocalMatrix) {
SkMatrix inv;
if (!args.fLocalMatrix->invert(&inv)) {
return nullptr;
}
matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
return GrLinearGradient::Make(GrGradientEffect::CreateArgs( return GrLinearGradient::Make(GrGradientEffect::CreateArgs(

View File

@ -162,10 +162,19 @@ void GrRadialGradient::GLSLRadialProcessor::emitCode(EmitArgs& args) {
std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor( std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
const GrFPArgs& args) const { const GrFPArgs& args) const {
SkASSERT(args.fContext);
SkMatrix matrix; SkMatrix matrix;
if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { if (!this->getLocalMatrix().invert(&matrix)) {
return nullptr; return nullptr;
} }
if (args.fLocalMatrix) {
SkMatrix inv;
if (!args.fLocalMatrix->invert(&inv)) {
return nullptr;
}
matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
return GrRadialGradient::Make(GrGradientEffect::CreateArgs( return GrRadialGradient::Make(GrGradientEffect::CreateArgs(

View File

@ -216,9 +216,16 @@ void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor( std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
const GrFPArgs& args) const { const GrFPArgs& args) const {
SkMatrix matrix; SkMatrix matrix;
if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { if (!this->getLocalMatrix().invert(&matrix)) {
return nullptr; return nullptr;
} }
if (args.fLocalMatrix) {
SkMatrix inv;
if (!args.fLocalMatrix->invert(&inv)) {
return nullptr;
}
matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit); matrix.postConcat(fPtsToUnit);
return GrSweepGradient::Make( return GrSweepGradient::Make(

View File

@ -175,13 +175,9 @@ void SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const {
std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor( std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
const GrFPArgs& args) const { const GrFPArgs& args) const {
SkMatrix matrix; SkASSERT(args.fContext);
if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
return nullptr;
}
return Gr2PtConicalGradientEffect::Make( return Gr2PtConicalGradientEffect::Make(
GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode, GrGradientEffect::CreateArgs(args.fContext, this, args.fLocalMatrix, fTileMode,
args.fDstColorSpaceInfo->colorSpace())); args.fDstColorSpaceInfo->colorSpace()));
} }

View File

@ -388,7 +388,18 @@ std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
const SkTwoPointConicalGradient& shader = const SkTwoPointConicalGradient& shader =
*static_cast<const SkTwoPointConicalGradient*>(args.fShader); *static_cast<const SkTwoPointConicalGradient*>(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, GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fWrapMode,
args.fDstColorSpace); args.fDstColorSpace);
// Data and matrix has to be prepared before constructing TwoPointConicalEffect so its parent // Data and matrix has to be prepared before constructing TwoPointConicalEffect so its parent

View File

@ -479,7 +479,8 @@ static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrC
sk_sp<SkShader> shader = SkGradientShader::MakeLinear( sk_sp<SkShader> shader = SkGradientShader::MakeLinear(
pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
GrColorSpaceInfo colorSpaceInfo(nullptr, kRGBA_8888_GrPixelConfig); 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); return as_SB(shader)->asFragmentProcessor(args);
} }