blob: aee2c9c885cdcea269bbd9647d52b64057f39027 [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRasterPipeline.h"
#include "src/shaders/SkTransformShader.h"
SkTransformShader::SkTransformShader(const SkShaderBase& shader) : fShader{shader} {}
skvm::Color SkTransformShader::onProgram(skvm::Builder* b,
skvm::Coord device, skvm::Coord local, skvm::Color color,
const SkMatrixProvider& matrices, const SkMatrix* localM,
const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::Coord newLocal = this->applyMatrix(b, matrices.localToDevice(), local, uniforms);
SkMatrixProvider matrixProvider{SkMatrix::I()};
return fShader.program(
b, device, newLocal, color, matrixProvider, localM, dst, uniforms, alloc);
}
skvm::Coord SkTransformShader::applyMatrix(
skvm::Builder* b, const SkMatrix& matrix, skvm::Coord local,
skvm::Uniforms* uniforms) const {
fMatrix = uniforms->pushPtr(&fMatrixStorage);
skvm::F32 x = local.x,
y = local.y;
auto dot = [&,x,y](int row) {
return b->mad(x, b->arrayF(fMatrix, 3*row+0),
b->mad(y, b->arrayF(fMatrix, 3*row+1),
b->arrayF(fMatrix, 3*row+2)));
};
x = dot(0);
y = dot(1);
fProcessingAsPerspective = matrix.hasPerspective() || fShader.getLocalMatrix().hasPerspective();
if (fProcessingAsPerspective) {
x = x * (1.0f / dot(2));
y = y * (1.0f / dot(2));
}
return {x, y};
}
void SkTransformShader::appendMatrix(const SkMatrix& matrix, SkRasterPipeline* p) const {
fProcessingAsPerspective = matrix.hasPerspective() || fShader.getLocalMatrix().hasPerspective();
if (fProcessingAsPerspective) {
p->append(SkRasterPipeline::matrix_perspective, fMatrixStorage);
} else {
p->append(SkRasterPipeline::matrix_2x3, fMatrixStorage);
}
}
bool SkTransformShader::update(const SkMatrix& ctm) const {
if (SkMatrix matrix; fShader.computeTotalInverse(ctm, nullptr, &matrix)) {
if (!fProcessingAsPerspective) {
SkASSERT(!matrix.hasPerspective());
if (matrix.hasPerspective()) {
return false;
}
}
matrix.get9(fMatrixStorage);
return true;
}
return false;
}
bool SkTransformShader::onAppendStages(const SkStageRec& rec) const {
// TODO
return false;
}