Reland "Fix handling of MaskFilter matrices"
This reverts commitc64ee20e13
. 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 commit2097fd03ff
. > > 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:
parent
f70b22ec36
commit
c6c5eade82
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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) {}
|
||||
, fDstColorSpaceInfo(dstColorSpaceInfo) {
|
||||
SkASSERT(fContext);
|
||||
SkASSERT(fViewMatrix);
|
||||
}
|
||||
|
||||
GrFPArgs(GrContext* context,
|
||||
const SkMatrix* viewMatrix,
|
||||
SkFilterQuality filterQuality,
|
||||
const GrColorSpaceInfo* dstColorSpaceInfo)
|
||||
: fContext(context)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fLocalMatrix(nullptr)
|
||||
, fFilterQuality(filterQuality)
|
||||
, fDstColorSpaceInfo(dstColorSpaceInfo) {}
|
||||
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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "SkMask.h"
|
||||
#include "SkMatrix.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkTLazy.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrFPArgs.h"
|
||||
@ -185,10 +186,17 @@ 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,
|
||||
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 {
|
||||
return false;
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user