/* * 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 "GrPathProcessor.h" #include "GrShaderCaps.h" #include "SkTo.h" #include "gl/GrGLGpu.h" #include "gl/GrGLVaryingHandler.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLPrimitiveProcessor.h" #include "glsl/GrGLSLUniformHandler.h" #include "glsl/GrGLSLVarying.h" class GrGLPathProcessor : public GrGLSLPrimitiveProcessor { public: GrGLPathProcessor() : fColor(GrColor_ILLEGAL) {} 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(); if (!pathProc.viewMatrix().hasPerspective()) { args.fVaryingHandler->setNoPerspective(); } // emit transforms this->emitTransforms(args.fVaryingHandler, args.fFPCoordTransformHandler); // Setup uniform color const char* stagedLocalVarName; fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "Color", &stagedLocalVarName); fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName); // setup constant solid coverage fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage); } void emitTransforms(GrGLSLVaryingHandler* varyingHandler, FPCoordTransformHandler* transformHandler) { int i = 0; while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) { GrSLType varyingType = coordTransform->getMatrix().hasPerspective() ? kHalf3_GrSLType : kHalf2_GrSLType; SkString strVaryingName; strVaryingName.printf("TransformedCoord_%d", i); GrGLSLVarying v(varyingType); GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*) varyingHandler; fInstalledTransforms.push_back().fHandle = glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(), &v).toIndex(); fInstalledTransforms.back().fType = varyingType; transformHandler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType); ++i; } } void setData(const GrGLSLProgramDataManager& pd, const GrPrimitiveProcessor& primProc, FPCoordTransformIter&& transformIter) override { const GrPathProcessor& pathProc = primProc.cast(); if (pathProc.color() != fColor) { float c[4]; GrColorToRGBAFloat(pathProc.color(), c); pd.set4fv(fColorUniform, 1, c); fColor = pathProc.color(); } int t = 0; while (const GrCoordTransform* coordTransform = transformIter.next()) { SkASSERT(fInstalledTransforms[t].fHandle.isValid()); const SkMatrix& m = GetTransformMatrix(pathProc.localMatrix(), *coordTransform); if (fInstalledTransforms[t].fCurrentValue.cheapEqualTo(m)) { continue; } fInstalledTransforms[t].fCurrentValue = m; SkASSERT(fInstalledTransforms[t].fType == kHalf2_GrSLType || fInstalledTransforms[t].fType == kHalf3_GrSLType); unsigned components = fInstalledTransforms[t].fType == kHalf2_GrSLType ? 2 : 3; pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m); ++t; } } private: typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle; struct TransformVarying { VaryingHandle fHandle; SkMatrix fCurrentValue = SkMatrix::InvalidMatrix(); GrSLType fType = kVoid_GrSLType; }; SkTArray fInstalledTransforms; UniformHandle fColorUniform; GrColor fColor; typedef GrGLSLPrimitiveProcessor INHERITED; }; GrPathProcessor::GrPathProcessor(GrColor 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(); }