Reland "Fix handling of MaskFilter matrices"

This reverts commit c64ee20e13.

Reason for revert: initial failures should be fixed in https://skia.googlesource.com/skia.git/+/8eaf64ae12696d4189d3cea9f023658494cf82b8

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

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

Change-Id: If194862a928d1abe22ed8fa968436c725d19a8fc
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7744
Reviewed-on: https://skia-review.googlesource.com/120480
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2018-04-11 15:33:40 -04:00 committed by Skia Commit-Bot
parent f70b22ec36
commit c6c5eade82
21 changed files with 268 additions and 149 deletions

View File

@ -11,6 +11,7 @@
#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,
@ -220,3 +221,92 @@ 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, 1500, 1000) {
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,7 +50,14 @@ public:
static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB,
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;
SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)

View File

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

View File

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

View File

@ -9,39 +9,86 @@
#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) {}
, fDstColorSpaceInfo(dstColorSpaceInfo) {
SkASSERT(fContext);
SkASSERT(fViewMatrix);
}
class WithPreLocalMatrix;
class WithPostLocalMatrix;
GrContext* fContext;
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;
const GrColorSpaceInfo* fDstColorSpaceInfo;
};
class GrFPArgs::WithPreLocalMatrix final : public GrFPArgs {
public:
WithPreLocalMatrix(const GrFPArgs& args, const SkMatrix& lm) : INHERITED(args) {
if (!lm.isIdentity()) {
if (fPreLocalMatrix) {
fStorage.setConcat(lm, *fPreLocalMatrix);
fPreLocalMatrix = fStorage.isIdentity() ? nullptr : &fStorage;
} else {
fPreLocalMatrix = &lm;
}
}
}
private:
WithPreLocalMatrix(const WithPreLocalMatrix&) = delete;
WithPreLocalMatrix& operator=(const WithPreLocalMatrix&) = delete;
SkMatrix fStorage;
using INHERITED = GrFPArgs;
};
class GrFPArgs::WithPostLocalMatrix final : public GrFPArgs {
public:
WithPostLocalMatrix(const GrFPArgs& args, const SkMatrix& lm) : INHERITED(args) {
if (!lm.isIdentity()) {
if (fPostLocalMatrix) {
fStorage.setConcat(*fPostLocalMatrix, lm);
fPostLocalMatrix = fStorage.isIdentity() ? nullptr : &fStorage;
} else {
fPostLocalMatrix = &lm;
}
}
}
private:
WithPostLocalMatrix(const WithPostLocalMatrix&) = delete;
WithPostLocalMatrix& operator=(const WithPostLocalMatrix&) = delete;
SkMatrix fStorage;
using INHERITED = GrFPArgs;
};
#endif

View File

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

View File

@ -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()->makeWithLocalMatrix(ctm));
tmpUnfiltered.setMaskFilter(tmpUnfiltered.getMaskFilter()->makeWithMatrix(ctm));
}
tmpUnfiltered.setImageFilter(nullptr);

View File

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

View File

@ -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;

View File

@ -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));
return as_SB(fProxyShader)->asFragmentProcessor(
GrFPArgs::WithPreLocalMatrix(args, this->getLocalMatrix()));
}
#endif

View File

@ -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) {

View File

@ -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.get();
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.get();
PictureShaderContext* ctx =
alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc);
@ -369,20 +380,24 @@ 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);
}
// We want to *reset* args.fPreLocalMatrix, not compose it.
GrFPArgs newArgs(args.fContext, args.fViewMatrix, args.fFilterQuality, args.fDstColorSpaceInfo);
newArgs.fPreLocalMatrix = lm.get();
return as_SB(bitmapShader)->asFragmentProcessor(newArgs);
}
#endif

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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()));
}

View File

@ -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

View File

@ -479,8 +479,7 @@ static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrC
sk_sp<SkShader> shader = SkGradientShader::MakeLinear(
pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
GrColorSpaceInfo colorSpaceInfo(nullptr, kRGBA_8888_GrPixelConfig);
GrFPArgs args(ctx, &SkMatrix::I(), &SkMatrix::I(), SkFilterQuality::kLow_SkFilterQuality,
&colorSpaceInfo);
GrFPArgs args(ctx, &SkMatrix::I(), SkFilterQuality::kLow_SkFilterQuality, &colorSpaceInfo);
return as_SB(shader)->asFragmentProcessor(args);
}