diff options
Diffstat (limited to 'src/shaders/SkPictureShader.cpp')
-rw-r--r-- | src/shaders/SkPictureShader.cpp | 69 |
1 files changed, 45 insertions, 24 deletions
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp index 21bd5a531c..097a60515e 100644 --- a/src/shaders/SkPictureShader.cpp +++ b/src/shaders/SkPictureShader.cpp @@ -38,7 +38,6 @@ public: SkShader::TileMode tmx, SkShader::TileMode tmy, const SkSize& scale, - const SkMatrix& localMatrix, SkTransferFunctionBehavior blendBehavior) : fColorSpace(std::move(colorSpace)) , fTile(tile) @@ -47,15 +46,10 @@ public: , fScale(scale) , fBlendBehavior(blendBehavior) { - for (int i = 0; i < 9; ++i) { - fLocalMatrixStorage[i] = localMatrix[i]; - } - static const size_t keySize = sizeof(fColorSpace) + sizeof(fTile) + sizeof(fTmx) + sizeof(fTmy) + sizeof(fScale) + - sizeof(fLocalMatrixStorage) + sizeof(fBlendBehavior); // This better be packed. SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - (uint32_t*)&fColorSpace) == keySize); @@ -79,7 +73,6 @@ private: SkRect fTile; SkShader::TileMode fTmx, fTmy; SkSize fScale; - SkScalar fLocalMatrixStorage[9]; SkTransferFunctionBehavior fBlendBehavior; SkDEBUGCODE(uint32_t fEndOfStruct;) @@ -179,16 +172,28 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const { fPicture->flatten(buffer); } -sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, const SkMatrix* localM, +// This helper returns two artifacts: +// +// 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(), +// 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, SkColorSpace* dstColorSpace, + SkMatrix* compositeLocalMatrix, const int maxTextureSize) const { SkASSERT(fPicture && !fPicture->cullRect().isEmpty()); - SkMatrix m; - m.setConcat(viewMatrix, this->getLocalMatrix()); - if (localM) { - m.preConcat(*localM); + *compositeLocalMatrix = this->getLocalMatrix(); + if (outerLocalMatrix) { + compositeLocalMatrix->preConcat(*outerLocalMatrix); } + const SkMatrix m = SkMatrix::Concat(viewMatrix, *compositeLocalMatrix); // Use a rotation-invariant scale SkPoint scale; @@ -246,7 +251,6 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, con fTmx, fTmy, tileScale, - this->getLocalMatrix(), blendBehavior); if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { @@ -265,14 +269,14 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, con tileImage = tileImage->makeColorSpace(fColorSpace, SkTransferFunctionBehavior::kIgnore); } - SkMatrix shaderMatrix = this->getLocalMatrix(); - shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); - tileShader = tileImage->makeShader(fTmx, fTmy, &shaderMatrix); + tileShader = tileImage->makeShader(fTmx, fTmy); SkResourceCache::Add(new BitmapShaderRec(key, tileShader.get())); fAddedToCache.store(true); } + compositeLocalMatrix->preScale(1 / tileScale.width(), 1 / tileScale.height()); + return tileShader; } @@ -284,21 +288,32 @@ bool SkPictureShader::onIsRasterPipelineOnly(const SkMatrix& ctm) const { bool SkPictureShader::onAppendStages(const StageRec& rec) const { // Keep bitmapShader alive by using alloc instead of stack memory auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>(); - bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS); - return bitmapShader && as_SB(bitmapShader)->appendStages(rec); + SkMatrix compositeLocalMatrix; + bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS, &compositeLocalMatrix); + + StageRec localRec = rec; + localRec.fLocalM = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix; + + return bitmapShader && as_SB(bitmapShader)->appendStages(localRec); } ///////////////////////////////////////////////////////////////////////////////////////// SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { - sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix, - rec.fDstColorSpace)); + SkMatrix compositeLocalMatrix; + sk_sp<SkShader> bitmapShader = this->refBitmapShader(*rec.fMatrix, + rec.fLocalMatrix, + rec.fDstColorSpace, + &compositeLocalMatrix); if (!bitmapShader) { return nullptr; } + ContextRec localRec = rec; + localRec.fLocalMatrix = compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix; + PictureShaderContext* ctx = - alloc->make<PictureShaderContext>(*this, rec, std::move(bitmapShader), alloc); + alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc); if (nullptr == ctx->fBitmapShaderContext) { ctx = nullptr; } @@ -362,14 +377,20 @@ 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, args.fDstColorSpaceInfo->colorSpace(), + &compositeLocalMatrix, maxTextureSize)); if (!bitmapShader) { return nullptr; } - return as_SB(bitmapShader) - ->asFragmentProcessor(GrFPArgs(args.fContext, args.fViewMatrix, - args.fFilterQuality, args.fDstColorSpaceInfo)); + + return as_SB(bitmapShader)->asFragmentProcessor( + GrFPArgs(args.fContext, + args.fViewMatrix, + compositeLocalMatrix.isIdentity() ? nullptr : &compositeLocalMatrix, + args.fFilterQuality, + args.fDstColorSpaceInfo)); } #endif |