| /* |
| * 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 GrGLGeometryProcessor_DEFINED |
| #define GrGLGeometryProcessor_DEFINED |
| |
| #include "GrGLPrimitiveProcessor.h" |
| |
| class GrGLGPBuilder; |
| |
| /** |
| * 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 GrGLGeometryProcessor : public GrGLPrimitiveProcessor { |
| 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 GrGLProgramDataManager& 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 GrGLProgramDataManager& 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(GrGLGPBuilder* gp, |
| const GrShaderVar& posVar, |
| const char* localCoords, |
| const TransformsIn& tin, |
| TransformsOut* tout) { |
| this->emitTransforms(gp, posVar, localCoords, SkMatrix::I(), tin, tout); |
| } |
| |
| // Emit pre-transformed coords as a vertex attribute per coord-transform. |
| void emitTransforms(GrGLGPBuilder*, |
| const GrShaderVar& posVar, |
| const char* localCoords, |
| const SkMatrix& localMatrix, |
| const TransformsIn&, |
| TransformsOut*); |
| |
| // caller has emitted transforms via attributes |
| void emitTransforms(GrGLGPBuilder*, |
| 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(GrGLGPBuilder*, GrGPArgs*, const char* posName); |
| void setupPosition(GrGLGPBuilder*, 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 GrGLProgramDataManager& 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 GrGLPrimitiveProcessor INHERITED; |
| }; |
| |
| #endif |