Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
SkShaders::MatrixRec Class Reference

#include <SkShaderBase.h>

Public Member Functions

 MatrixRec ()=default
 
 MatrixRec (const SkMatrix &ctm)
 
MatrixRec concat (const SkMatrix &m) const
 
std::optional< MatrixRecapply (const SkStageRec &rec, const SkMatrix &postInv={}) const
 
std::tuple< SkMatrix, bool > applyForFragmentProcessor (const SkMatrix &postInv) const
 
MatrixRec applied () const
 
void markTotalMatrixInvalid ()
 
void markCTMApplied ()
 
bool totalMatrixIsValid () const
 
SkMatrix totalMatrix () const
 
bool totalInverse (SkMatrix *out) const
 
bool hasPendingMatrix () const
 
bool rasterPipelineCoordsAreSeeded () const
 

Detailed Description

This is used to accumulate matrices, starting with the CTM, when building up SkRasterPipeline 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", 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 of the "total matrix" and if Android Framework could be updated to not use backwards local matrix concatenation this could just be replaced by a simple SkMatrix or SkM44 passed down during traversal.

Definition at line 57 of file SkShaderBase.h.

Constructor & Destructor Documentation

◆ MatrixRec() [1/2]

SkShaders::MatrixRec::MatrixRec ( )
default

◆ MatrixRec() [2/2]

SkShaders::MatrixRec::MatrixRec ( const SkMatrix ctm)
explicit

Definition at line 22 of file SkShaderBase.cpp.

22: fCTM(ctm) {}

Member Function Documentation

◆ applied()

MatrixRec SkShaders::MatrixRec::applied ( ) const

A parent FP may need to create a FP for its child by calling SkShaderBase::asFragmentProcessor() and then pass the result to the apply() above. This comes up when the parent needs to ensure pending matrices are applied before the child because the parent is going to manipulate the coordinates after any pending matrix and pass the resulting coords to the child. This function gets a MatrixRec that reflects the state after this MatrixRec has bee applied but it does not apply it! Example: auto childFP = fChild->asFragmentProcessor(args, mrec.applied()); childFP = MakeAWrappingFPThatModifiesChildsCoords(std::move(childFP)); auto [success, parentFP] = mrec.apply(std::move(childFP));

Definition at line 54 of file SkShaderBase.cpp.

54 {
55 // We mark the CTM as "not applied" because we *never* apply the CTM for FPs. Their starting
56 // coords are local, not device, coords.
57 return MatrixRec{fCTM,
58 fTotalLocalMatrix,
59 /*pendingLocalMatrix=*/SkMatrix::I(),
60 fTotalMatrixIsValid,
61 /*ctmApplied=*/false};
62}
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544

◆ apply()

std::optional< MatrixRec > SkShaders::MatrixRec::apply ( const SkStageRec rec,
const SkMatrix postInv = {} 
) const

Appends a mul by the inverse of the pending local matrix to the pipeline. 'postInv' is an additional matrix to post-apply to the inverted pending matrix. If the pending matrix is not invertible the std::optional result won't have a value and the pipeline will be unmodified.

Definition at line 24 of file SkShaderBase.cpp.

24 {
25 SkMatrix total = fPendingLocalMatrix;
26 if (!fCTMApplied) {
27 total = SkMatrix::Concat(fCTM, total);
28 }
29 if (!total.invert(&total)) {
30 return {};
31 }
32 total = SkMatrix::Concat(postInv, total);
33 if (!fCTMApplied) {
34 rec.fPipeline->append(SkRasterPipelineOp::seed_shader);
35 }
36 // appendMatrix is a no-op if total worked out to identity.
37 rec.fPipeline->appendMatrix(rec.fAlloc, total);
38 return MatrixRec{fCTM,
39 fTotalLocalMatrix,
40 /*pendingLocalMatrix=*/SkMatrix::I(),
41 fTotalMatrixIsValid,
42 /*ctmApplied=*/true};
43}
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrix.h:1775
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
void append(SkRasterPipelineOp, void *=nullptr)
void appendMatrix(SkArenaAlloc *, const SkMatrix &)
SkRasterPipeline * fPipeline
Definition: SkEffectPriv.h:21
SkArenaAlloc * fAlloc
Definition: SkEffectPriv.h:22

◆ applyForFragmentProcessor()

std::tuple< SkMatrix, bool > SkShaders::MatrixRec::applyForFragmentProcessor ( const SkMatrix postInv) const

FP matrices work differently than SkRasterPipeline. The starting coordinates provided to the root SkShader's FP are already in local space. So we never apply the inverse CTM. This returns the inverted pending local matrix with the provided postInv matrix applied after it. If the pending local matrix cannot be inverted, the boolean is false.

Definition at line 45 of file SkShaderBase.cpp.

45 {
46 SkASSERT(!fCTMApplied);
47 SkMatrix total;
48 if (!fPendingLocalMatrix.invert(&total)) {
49 return {SkMatrix::I(), false};
50 }
51 return {SkMatrix::Concat(postInv, total), true};
52}
#define SkASSERT(cond)
Definition: SkAssert.h:116

◆ concat()

MatrixRec SkShaders::MatrixRec::concat ( const SkMatrix m) const

Returns a new MatrixRec that represents the existing total and pending matrix pre-concat'ed with m.

Definition at line 64 of file SkShaderBase.cpp.

64 {
65 return {fCTM,
66 SkShaderBase::ConcatLocalMatrices(fTotalLocalMatrix, m),
67 SkShaderBase::ConcatLocalMatrices(fPendingLocalMatrix, m),
68 fTotalMatrixIsValid,
69 fCTMApplied};
70}
static SkMatrix ConcatLocalMatrices(const SkMatrix &parentLM, const SkMatrix &childLM)
Definition: SkShaderBase.h:384

◆ hasPendingMatrix()

bool SkShaders::MatrixRec::hasPendingMatrix ( ) const
inline

Is there a transform that has not yet been applied by a parent shader?

Definition at line 125 of file SkShaderBase.h.

125 {
126 return (!fCTMApplied && !fCTM.isIdentity()) || !fPendingLocalMatrix.isIdentity();
127 }
bool isIdentity() const
Definition: SkMatrix.h:223

◆ markCTMApplied()

void SkShaders::MatrixRec::markCTMApplied ( )
inline

Marks the CTM as already applied; can avoid re-seeding the shader unnecessarily.

Definition at line 104 of file SkShaderBase.h.

104{ fCTMApplied = true; }

◆ markTotalMatrixInvalid()

void SkShaders::MatrixRec::markTotalMatrixInvalid ( )
inline

Call to indicate that the mapping from shader to device space is not known.

Definition at line 101 of file SkShaderBase.h.

101{ fTotalMatrixIsValid = false; }

◆ rasterPipelineCoordsAreSeeded()

bool SkShaders::MatrixRec::rasterPipelineCoordsAreSeeded ( ) const
inline

When generating raster pipeline, have the device coordinates been seeded?

Definition at line 130 of file SkShaderBase.h.

130{ return fCTMApplied; }

◆ totalInverse()

bool SkShaders::MatrixRec::totalInverse ( SkMatrix out) const
inline

Gets the inverse of totalMatrix(), if invertible.

Definition at line 120 of file SkShaderBase.h.

120 {
121 return this->totalMatrix().invert(out);
122 }
SkMatrix totalMatrix() const
Definition: SkShaderBase.h:117

◆ totalMatrix()

SkMatrix SkShaders::MatrixRec::totalMatrix ( ) const
inline

Gets the total transform from the current shader's space to device space. This may or may not be valid. Shaders should avoid making decisions based on this matrix if totalMatrixIsValid() is false.

Definition at line 117 of file SkShaderBase.h.

117{ return SkMatrix::Concat(fCTM, fTotalLocalMatrix); }

◆ totalMatrixIsValid()

bool SkShaders::MatrixRec::totalMatrixIsValid ( ) const
inline

Indicates whether the total matrix of a MatrixRec passed to a SkShader actually represents the full transform between that shader's coordinate space and device space.

Definition at line 110 of file SkShaderBase.h.

110{ return fTotalMatrixIsValid; }

The documentation for this class was generated from the following files: