aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders/SkPictureShader.cpp
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-02-06 16:49:40 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-06 22:13:05 +0000
commit18f7e0a19c1c49047f3f57c79852c7fd62918365 (patch)
tree0c947e69ae11ea9b5ec9adad2064a463ae2d7333 /src/shaders/SkPictureShader.cpp
parent133bc33330d3e131a641d08cdfbf383c14c86c30 (diff)
Fix picture shader handling of outer local matrix
Instead of applying local matrices to the cached shader, pass them explicitly/composed to createContext/appendStages/asFragmentProcessor. Change-Id: I39aaf07ac883094c447c4e03e2ef9dcf8de13555 Reviewed-on: https://skia-review.googlesource.com/104580 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
Diffstat (limited to 'src/shaders/SkPictureShader.cpp')
-rw-r--r--src/shaders/SkPictureShader.cpp69
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