blob: 82f016160d440c7a9468a12410a4c668b588eaca [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/GrPathProcessor.h"
#include "include/private/SkTo.h"
#include "src/core/SkMatrixPriv.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/gl/GrGLGpu.h"
#ifdef SK_GL
#include "src/gpu/gl/GrGLVaryingHandler.h"
#endif
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
public:
GrGLPathProcessor() : fColor(SK_PMColor4fILLEGAL) {}
static void GenKey(const GrPathProcessor& pathProc,
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
b->add32(SkToInt(pathProc.viewMatrix().hasPerspective()));
}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
if (!pathProc.viewMatrix().hasPerspective()) {
args.fVaryingHandler->setNoPerspective();
}
// emit transforms
this->emitTransforms(args.fVaryingHandler, args.fUniformHandler,
args.fFPCoordTransformHandler);
// Setup uniform color
const char* stagedLocalVarName;
fColorUniform = args.fUniformHandler->addUniform(nullptr,
kFragment_GrShaderFlag,
kHalf4_GrSLType,
"Color",
&stagedLocalVarName);
fragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, stagedLocalVarName);
// setup constant solid coverage
fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
}
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
GrGLSLUniformHandler* uniformHandler,
FPCoordTransformHandler* transformHandler) {
for (int i = 0; *transformHandler; ++*transformHandler, ++i) {
SkString strVaryingName;
strVaryingName.printf("TransformedCoord_%d", i);
GrGLSLVarying v(kFloat2_GrSLType);
#ifdef SK_GL
GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*)varyingHandler;
fVaryingTransform.push_back().fHandle =
glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(), &v)
.toIndex();
#endif
GrShaderVar fragmentVar = {SkString(v.fsIn()), kFloat2_GrSLType};
transformHandler->specifyCoordsForCurrCoordTransform(fragmentVar);
}
}
void setData(const GrGLSLProgramDataManager& pd,
const GrPrimitiveProcessor& primProc) override {
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
if (pathProc.color() != fColor) {
pd.set4fv(fColorUniform, 1, pathProc.color().vec());
fColor = pathProc.color();
}
for (int v = 0; v < fVaryingTransform.count(); ++v) {
if (fVaryingTransform[v].fHandle.isValid()) {
SkMatrix m = pathProc.localMatrix();
if (!SkMatrixPriv::CheapEqual(fVaryingTransform[v].fCurrentValue, m)) {
fVaryingTransform[v].fCurrentValue = m;
pd.setPathFragmentInputTransform(fVaryingTransform[v].fHandle, 2, m);
}
}
}
}
private:
using VaryingHandle = GrGLSLProgramDataManager::VaryingHandle;
// Varying transforms are used for non-explicitly sampled FPs. We provide a matrix
// to GL as fixed function state and it uses it to compute a varying that we pick up
// in the FS as the transformed local coords.
struct TransformVarying {
VaryingHandle fHandle;
SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
};
SkTArray<TransformVarying, true> fVaryingTransform;
UniformHandle fColorUniform;
SkPMColor4f fColor;
using INHERITED = GrGLSLPrimitiveProcessor;
};
GrPathProcessor::GrPathProcessor(const SkPMColor4f& color,
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix)
: INHERITED(kGrPathProcessor_ClassID)
, fColor(color)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix) {}
void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLPathProcessor::GenKey(*this, caps, b);
}
GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const {
SkASSERT(caps.pathRenderingSupport());
return new GrGLPathProcessor();
}