/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrGLSLGeometryProcessor_DEFINED #define GrGLSLGeometryProcessor_DEFINED #include "GrGLSLPrimitiveProcessor.h" class GrGLSLGPBuilder; /** * If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit * from this class. Since paths don't have vertices, this class is only meant to be used internally * by skia, for special cases. */ class GrGLSLGeometryProcessor : public GrGLSLPrimitiveProcessor { public: /* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */ void emitCode(EmitArgs&) override; // By default we use the identity matrix void setTransformData(const GrPrimitiveProcessor&, const GrGLSLProgramDataManager& pdman, int index, const SkTArray<const GrCoordTransform*, true>& transforms) override { this->setTransformDataMatrix(SkMatrix::I(), pdman, index, transforms); } // A helper which subclasses can use if needed template <class GeometryProcessor> void setTransformDataHelper(const GrPrimitiveProcessor& primProc, const GrGLSLProgramDataManager& pdman, int index, const SkTArray<const GrCoordTransform*, true>& transforms) { const GeometryProcessor& gp = primProc.cast<GeometryProcessor>(); this->setTransformDataMatrix(gp.localMatrix(), pdman, index, transforms); } protected: // Emit a uniform matrix for each coord transform. void emitTransforms(GrGLSLVertexBuilder* vb, GrGLSLVaryingHandler* varyingHandler, GrGLSLUniformHandler* uniformHandler, const GrShaderVar& posVar, const char* localCoords, const TransformsIn& tin, TransformsOut* tout) { this->emitTransforms(vb, varyingHandler, uniformHandler, posVar, localCoords, SkMatrix::I(), tin, tout); } // Emit pre-transformed coords as a vertex attribute per coord-transform. void emitTransforms(GrGLSLVertexBuilder*, GrGLSLVaryingHandler*, GrGLSLUniformHandler*, const GrShaderVar& posVar, const char* localCoords, const SkMatrix& localMatrix, const TransformsIn&, TransformsOut*); // caller has emitted transforms via attributes void emitTransforms(GrGLSLVertexBuilder*, GrGLSLVaryingHandler*, const char* localCoords, const TransformsIn& tin, TransformsOut* tout); struct GrGPArgs { // The variable used by a GP to store its position. It can be // either a vec2 or a vec3 depending on the presence of perspective. GrShaderVar fPositionVar; }; // Create the correct type of position variable given the CTM void setupPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName); void setupPosition(GrGLSLVertexBuilder*, GrGLSLUniformHandler* uniformHandler, GrGPArgs*, const char* posName, const SkMatrix& mat, UniformHandle* viewMatrixUniform); static uint32_t ComputePosKey(const SkMatrix& mat) { if (mat.isIdentity()) { return 0x0; } else if (!mat.hasPerspective()) { return 0x01; } else { return 0x02; } } private: void setTransformDataMatrix(const SkMatrix& localMatrix, const GrGLSLProgramDataManager& pdman, int index, const SkTArray<const GrCoordTransform*, true>& transforms) { SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index]; int numTransforms = transforms.count(); for (int t = 0; t < numTransforms; ++t) { SkASSERT(procTransforms[t].fHandle.isValid()); const SkMatrix& transform = GetTransformMatrix(localMatrix, *transforms[t]); if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) { pdman.setSkMatrix(procTransforms[t].fHandle.toIndex(), transform); procTransforms[t].fCurrentValue = transform; } } } virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0; typedef GrGLSLPrimitiveProcessor INHERITED; }; #endif