1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkTransformShader.h" 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkEffectPriv.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipeline.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipelineOpList.h" 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker #include <optional> 16*c8dee2aaSAndroid Build Coastguard Worker SkTransformShader(const SkShaderBase & shader,bool allowPerspective)17*c8dee2aaSAndroid Build Coastguard WorkerSkTransformShader::SkTransformShader(const SkShaderBase& shader, bool allowPerspective) 18*c8dee2aaSAndroid Build Coastguard Worker : fShader{shader}, fAllowPerspective{allowPerspective} { 19*c8dee2aaSAndroid Build Coastguard Worker SkMatrix::I().get9(fMatrixStorage); 20*c8dee2aaSAndroid Build Coastguard Worker } 21*c8dee2aaSAndroid Build Coastguard Worker update(const SkMatrix & matrix)22*c8dee2aaSAndroid Build Coastguard Workerbool SkTransformShader::update(const SkMatrix& matrix) { 23*c8dee2aaSAndroid Build Coastguard Worker if (!fAllowPerspective && matrix.hasPerspective()) { 24*c8dee2aaSAndroid Build Coastguard Worker return false; 25*c8dee2aaSAndroid Build Coastguard Worker } 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker matrix.get9(fMatrixStorage); 28*c8dee2aaSAndroid Build Coastguard Worker return true; 29*c8dee2aaSAndroid Build Coastguard Worker } 30*c8dee2aaSAndroid Build Coastguard Worker appendStages(const SkStageRec & rec,const SkShaders::MatrixRec & mRec) const31*c8dee2aaSAndroid Build Coastguard Workerbool SkTransformShader::appendStages(const SkStageRec& rec, 32*c8dee2aaSAndroid Build Coastguard Worker const SkShaders::MatrixRec& mRec) const { 33*c8dee2aaSAndroid Build Coastguard Worker // We have to seed and apply any constant matrices before appending our matrix that may 34*c8dee2aaSAndroid Build Coastguard Worker // mutate. We could try to add one matrix stage and then incorporate the parent matrix 35*c8dee2aaSAndroid Build Coastguard Worker // with the variable matrix in each call to update(). However, in practice our callers 36*c8dee2aaSAndroid Build Coastguard Worker // fold the CTM into the update() matrix and don't wrap the transform shader in local matrix 37*c8dee2aaSAndroid Build Coastguard Worker // shaders so the call to apply below should just seed the coordinates. If this assert fires 38*c8dee2aaSAndroid Build Coastguard Worker // it just indicates an optimization opportunity, not a correctness bug. 39*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!mRec.hasPendingMatrix()); 40*c8dee2aaSAndroid Build Coastguard Worker std::optional<SkShaders::MatrixRec> childMRec = mRec.apply(rec); 41*c8dee2aaSAndroid Build Coastguard Worker if (!childMRec.has_value()) { 42*c8dee2aaSAndroid Build Coastguard Worker return false; 43*c8dee2aaSAndroid Build Coastguard Worker } 44*c8dee2aaSAndroid Build Coastguard Worker // The matrix we're about to insert gets updated between uses of the pipeline so our children 45*c8dee2aaSAndroid Build Coastguard Worker // can't know the total transform when they add their stages. We don't even incorporate this 46*c8dee2aaSAndroid Build Coastguard Worker // matrix into the SkShaders::MatrixRec at all. 47*c8dee2aaSAndroid Build Coastguard Worker childMRec->markTotalMatrixInvalid(); 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard Worker auto type = fAllowPerspective ? SkRasterPipelineOp::matrix_perspective 50*c8dee2aaSAndroid Build Coastguard Worker : SkRasterPipelineOp::matrix_2x3; 51*c8dee2aaSAndroid Build Coastguard Worker rec.fPipeline->append(type, fMatrixStorage); 52*c8dee2aaSAndroid Build Coastguard Worker 53*c8dee2aaSAndroid Build Coastguard Worker fShader.appendStages(rec, *childMRec); 54*c8dee2aaSAndroid Build Coastguard Worker return true; 55*c8dee2aaSAndroid Build Coastguard Worker } 56