diff options
-rw-r--r-- | gm/pictureshader.cpp | 39 | ||||
-rw-r--r-- | src/shaders/SkPictureShader.cpp | 69 | ||||
-rw-r--r-- | src/shaders/SkPictureShader.h | 1 |
3 files changed, 71 insertions, 38 deletions
diff --git a/gm/pictureshader.cpp b/gm/pictureshader.cpp index bc98d80d1c..df91a33cce 100644 --- a/gm/pictureshader.cpp +++ b/gm/pictureshader.cpp @@ -25,10 +25,10 @@ static struct { class PictureShaderGM : public skiagm::GM { public: - PictureShaderGM(SkScalar tileSize, SkScalar sceneSize) + PictureShaderGM(SkScalar tileSize, SkScalar sceneSize, bool useLocalMatrixWrapper = false) : fTileSize(tileSize) - , fSceneSize(sceneSize) { - } + , fSceneSize(sceneSize) + , fUseLocalMatrixWrapper(useLocalMatrixWrapper) {} protected: void onOnceBeforeDraw() override { @@ -47,7 +47,7 @@ public: SkString onShortName() override { - return SkString("pictureshader"); + return SkStringPrintf("pictureshader%s", fUseLocalMatrixWrapper ? "_localwrapper" : ""); } SkISize onISize() override { @@ -151,32 +151,43 @@ private: canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint); - paint.setShader(SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx, - kTileConfigs[tileMode].tmy, &localMatrix, - nullptr)); + auto pictureShader = SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx, + kTileConfigs[tileMode].tmy, + fUseLocalMatrixWrapper + ? nullptr : &localMatrix, + nullptr); + paint.setShader(fUseLocalMatrixWrapper + ? pictureShader->makeWithLocalMatrix(localMatrix) + : pictureShader); canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); canvas->translate(fSceneSize * 1.1f, 0); - paint.setShader(SkShader::MakeBitmapShader(fBitmap, - kTileConfigs[tileMode].tmx, - kTileConfigs[tileMode].tmy, - &localMatrix)); + auto bitmapShader = SkShader::MakeBitmapShader(fBitmap, + kTileConfigs[tileMode].tmx, + kTileConfigs[tileMode].tmy, + fUseLocalMatrixWrapper + ? nullptr : &localMatrix); + paint.setShader(fUseLocalMatrixWrapper + ? bitmapShader->makeWithLocalMatrix(localMatrix) + : bitmapShader); canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); canvas->restore(); } - SkScalar fTileSize; - SkScalar fSceneSize; - sk_sp<SkPicture> fPicture; SkBitmap fBitmap; + SkScalar fTileSize; + SkScalar fSceneSize; + bool fUseLocalMatrixWrapper; + typedef GM INHERITED; }; DEF_GM(return new PictureShaderGM(50, 100);) +DEF_GM(return new PictureShaderGM(50, 100, true);) DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) { // https://code.google.com/p/skia/issues/detail?id=3398 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 diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h index fe388ee81d..3b7cab0f2d 100644 --- a/src/shaders/SkPictureShader.h +++ b/src/shaders/SkPictureShader.h @@ -49,6 +49,7 @@ private: sk_sp<SkShader> refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix, SkColorSpace* dstColorSpace, + SkMatrix* compositeLocalMatrix, const int maxTextureSize = 0) const; class PictureShaderContext : public Context { |