aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/pictureshader.cpp39
-rw-r--r--src/shaders/SkPictureShader.cpp69
-rw-r--r--src/shaders/SkPictureShader.h1
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 {