Use MatrixRec in legacy shader context code
Bug: skia:14076
Change-Id: I750222f18a1705e9e98ee21a6b4ec22d744b2c03
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/714818
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index d6bd265..dacec4c 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -770,8 +770,7 @@
if (paint->getShader()) {
shaderContext = as_SB(paint->getShader())
->makeContext({paint->getAlpha(),
- ctm,
- nullptr,
+ SkShaders::MatrixRec(ctm),
device.colorType(),
device.colorSpace(),
props},
diff --git a/src/shaders/SkBitmapProcShader.cpp b/src/shaders/SkBitmapProcShader.cpp
index dd4df85..911ffa5 100644
--- a/src/shaders/SkBitmapProcShader.cpp
+++ b/src/shaders/SkBitmapProcShader.cpp
@@ -79,7 +79,7 @@
{
SkMatrix totalInverse;
// Do this first, so we know the matrix can be inverted.
- if (!shader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &totalInverse)) {
+ if (!rec.fMatrixRec.totalInverse(&totalInverse)) {
return nullptr;
}
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index a1056d1..c0e77b5 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -304,8 +304,7 @@
}
SkMatrix inv;
- if (!this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &inv) ||
- !legacy_shader_can_handle(inv)) {
+ if (!rec.fMatrixRec.totalInverse(&inv) || !legacy_shader_can_handle(inv)) {
return nullptr;
}
diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp
index e984f9c..9c0e164 100644
--- a/src/shaders/SkLocalMatrixShader.cpp
+++ b/src/shaders/SkLocalMatrixShader.cpp
@@ -6,7 +6,6 @@
*/
#include "src/shaders/SkLocalMatrixShader.h"
-#include "src/base/SkTLazy.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"
@@ -63,18 +62,9 @@
}
#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
-SkShaderBase::Context* SkLocalMatrixShader::onMakeContext(
- const ContextRec& rec, SkArenaAlloc* alloc) const
-{
- SkTCopyOnFirstWrite<SkMatrix> lm(fLocalMatrix);
- if (rec.fLocalMatrix) {
- *lm.writable() = ConcatLocalMatrices(*rec.fLocalMatrix, *lm);
- }
-
- ContextRec newRec(rec);
- newRec.fLocalMatrix = lm;
-
- return as_SB(fWrappedShader)->makeContext(newRec, alloc);
+SkShaderBase::Context* SkLocalMatrixShader::onMakeContext(const ContextRec& rec,
+ SkArenaAlloc* alloc) const {
+ return as_SB(fWrappedShader)->makeContext(ContextRec::Concat(rec, fLocalMatrix), alloc);
}
#endif
diff --git a/src/shaders/SkPerlinNoiseShaderImpl.cpp b/src/shaders/SkPerlinNoiseShaderImpl.cpp
index 374ee56..c41e4bf 100644
--- a/src/shaders/SkPerlinNoiseShaderImpl.cpp
+++ b/src/shaders/SkPerlinNoiseShaderImpl.cpp
@@ -223,18 +223,10 @@
}
#endif
-static inline SkMatrix total_matrix(const SkShaderBase::ContextRec& rec,
- const SkShaderBase& shader) {
- if (rec.fLocalMatrix) {
- return SkMatrix::Concat(*rec.fMatrix, *rec.fLocalMatrix);
- }
- return *rec.fMatrix;
-}
-
SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
const SkPerlinNoiseShader& shader, const ContextRec& rec)
: Context(shader, rec)
- , fMatrix(total_matrix(rec, shader)) // used for temp storage, adjusted below
+ , fMatrix(rec.fMatrixRec.totalMatrix()) // used for temp storage, adjusted below
, fPaintingData(shader.fTileSize,
shader.fSeed,
shader.fBaseFrequencyX,
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index 3435ea3..56eea11 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -313,13 +313,10 @@
/////////////////////////////////////////////////////////////////////////////////////////
#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
-SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc)
-const {
- const auto& vm = *rec.fMatrix;
- const auto* lm = rec.fLocalMatrix;
- const auto totalM = lm ? SkMatrix::Concat(vm, *lm) : vm;
- sk_sp<SkShader> bitmapShader = this->rasterShader(totalM, rec.fDstColorType,
- rec.fDstColorSpace, rec.fProps);
+SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec,
+ SkArenaAlloc* alloc) const {
+ sk_sp<SkShader> bitmapShader = this->rasterShader(
+ rec.fMatrixRec.totalMatrix(), rec.fDstColorType, rec.fDstColorSpace, rec.fProps);
if (!bitmapShader) {
return nullptr;
}
diff --git a/src/shaders/SkShaderBase.cpp b/src/shaders/SkShaderBase.cpp
index cfb2b74..0ad9cfb 100644
--- a/src/shaders/SkShaderBase.cpp
+++ b/src/shaders/SkShaderBase.cpp
@@ -113,12 +113,6 @@
void SkShaderBase::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); }
-bool SkShaderBase::computeTotalInverse(const SkMatrix& ctm,
- const SkMatrix* localMatrix,
- SkMatrix* totalInverse) const {
- return (localMatrix ? SkMatrix::Concat(ctm, *localMatrix) : ctm).invert(totalInverse);
-}
-
bool SkShaderBase::asLuminanceColor(SkColor* colorPtr) const {
SkColor storage;
if (nullptr == colorPtr) {
@@ -134,8 +128,8 @@
SkShaderBase::Context* SkShaderBase::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
// We always fall back to raster pipeline when perspective is present.
- if (rec.fMatrix->hasPerspective() || (rec.fLocalMatrix && rec.fLocalMatrix->hasPerspective()) ||
- !this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)) {
+ auto totalMatrix = rec.fMatrixRec.totalMatrix();
+ if (totalMatrix.hasPerspective() || !totalMatrix.invert(nullptr)) {
return nullptr;
}
@@ -146,14 +140,13 @@
}
SkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec)
- : fShader(shader), fCTM(*rec.fMatrix) {
+ : fShader(shader) {
// We should never use a context with perspective.
- SkASSERT(!rec.fMatrix->hasPerspective());
- SkASSERT(!rec.fLocalMatrix || !rec.fLocalMatrix->hasPerspective());
+ SkASSERT(!rec.fMatrixRec.totalMatrix().hasPerspective());
// Because the context parameters must be valid at this point, we know that the matrix is
// invertible.
- SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &fTotalInverse));
+ SkAssertResult(rec.fMatrixRec.totalInverse(&fTotalInverse));
fPaintAlpha = rec.fPaintAlpha;
}
@@ -190,16 +183,7 @@
// SkShader::Context::shadeSpan() handles the paint opacity internally,
// but SkRasterPipelineBlitter applies it as a separate stage.
// We skip the internal shadeSpan() step by forcing the alpha to be opaque.
-
- // We don't have a separate ctm and local matrix at this point. Just pass the combined matrix
- // as the CTM. TODO: thread the MatrixRec through the legacy context system.
- auto tm = mRec.totalMatrix();
- ContextRec cr(SK_AlphaOPAQUE,
- tm,
- nullptr,
- rec.fDstColorType,
- sk_srgb_singleton(),
- rec.fSurfaceProps);
+ ContextRec cr(SK_AlphaOPAQUE, mRec, rec.fDstColorType, sk_srgb_singleton(), rec.fSurfaceProps);
struct CallbackCtx : SkRasterPipeline_CallbackCtx {
sk_sp<const SkShader> shader;
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index e6381a4..5936d0f 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -50,15 +50,16 @@
namespace SkShaders {
/**
* This is used to accumulate matrices, starting with the CTM, when building up
- * SkRasterPipeline, SkVM, and GrFragmentProcessor by walking the SkShader tree. It avoids
+ * SkRasterPipeline, SkVM, or GrFragmentProcessor by walking the SkShader tree. It avoids
* adding a matrix multiply for each individual matrix. It also handles the reverse matrix
* concatenation order required by Android Framework, see b/256873449.
*
- * This also tracks the dubious concept of a "total matrix", which includes all the matrices
- * encountered during traversal to the current shader, including ones that have already been
- * applied. The total matrix represents the transformation from the current shader's coordinate
- * space to device space. It is dubious because it doesn't account for SkShaders that manipulate
- * the coordinates passed to their children, which may not even be representable by a matrix.
+ * This also tracks the dubious concept of a "total matrix", in the legacy Context/shadeSpan system.
+ * That includes all the matrices encountered during traversal to the current shader, including ones
+ * that have already been applied. The total matrix represents the transformation from the current
+ * shader's coordinate space to device space. It is dubious because it doesn't account for SkShaders
+ * that manipulate the coordinates passed to their children, which may not even be representable by
+ * a matrix.
*
* The total matrix is used for mipmap level selection and a filter downgrade optimizations in
* SkImageShader and sizing of the SkImage created by SkPictureShader. If we can remove usages
@@ -290,21 +291,30 @@
* ContextRec acts as a parameter bundle for creating Contexts.
*/
struct ContextRec {
- ContextRec(SkAlpha paintAlpha, const SkMatrix& matrix, const SkMatrix* localM,
- SkColorType dstColorType, SkColorSpace* dstColorSpace, SkSurfaceProps props)
- : fMatrix(&matrix)
- , fLocalMatrix(localM)
- , fDstColorType(dstColorType)
- , fDstColorSpace(dstColorSpace)
- , fProps(props)
- , fPaintAlpha(paintAlpha) {}
+ ContextRec(SkAlpha paintAlpha,
+ const SkShaders::MatrixRec& matrixRec,
+ SkColorType dstColorType,
+ SkColorSpace* dstColorSpace,
+ SkSurfaceProps props)
+ : fMatrixRec(matrixRec)
+ , fDstColorType(dstColorType)
+ , fDstColorSpace(dstColorSpace)
+ , fProps(props)
+ , fPaintAlpha(paintAlpha) {}
- const SkMatrix* fMatrix; // the current matrix in the canvas
- const SkMatrix* fLocalMatrix; // optional local matrix
- SkColorType fDstColorType; // the color type of the dest surface
- SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any)
- SkSurfaceProps fProps; // props of the dest surface
- SkAlpha fPaintAlpha;
+ static ContextRec Concat(const ContextRec& parentRec, const SkMatrix& localM) {
+ return {parentRec.fPaintAlpha,
+ parentRec.fMatrixRec.concat(localM),
+ parentRec.fDstColorType,
+ parentRec.fDstColorSpace,
+ parentRec.fProps};
+ }
+
+ const SkShaders::MatrixRec fMatrixRec;
+ SkColorType fDstColorType; // the color type of the dest surface
+ SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any)
+ SkSurfaceProps fProps; // props of the dest surface
+ SkAlpha fPaintAlpha;
bool isLegacyCompatible(SkColorSpace* shadersColorSpace) const;
};
@@ -337,14 +347,10 @@
uint8_t getPaintAlpha() const { return fPaintAlpha; }
const SkMatrix& getTotalInverse() const { return fTotalInverse; }
- const SkMatrix& getCTM() const { return fCTM; }
private:
- SkMatrix fCTM;
SkMatrix fTotalInverse;
uint8_t fPaintAlpha;
-
- using INHERITED = SkNoncopyable;
};
/**
@@ -379,10 +385,6 @@
*/
virtual bool appendStages(const SkStageRec&, const SkShaders::MatrixRec&) const;
- bool SK_WARN_UNUSED_RESULT computeTotalInverse(const SkMatrix& ctm,
- const SkMatrix* localMatrix,
- SkMatrix* totalInverse) const;
-
virtual SkImage* onIsAImage(SkMatrix*, SkTileMode[2]) const {
return nullptr;
}