1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrDefaultGeoProcFactory.h" 9 10 #include "GrInvariantOutput.h" 11 #include "SkRefCnt.h" 12 #include "glsl/GrGLSLFragmentShaderBuilder.h" 13 #include "glsl/GrGLSLGeometryProcessor.h" 14 #include "glsl/GrGLSLVertexShaderBuilder.h" 15 #include "glsl/GrGLSLVarying.h" 16 #include "glsl/GrGLSLUniformHandler.h" 17 #include "glsl/GrGLSLUtil.h" 18 19 /* 20 * The default Geometry Processor simply takes position and multiplies it by the uniform view 21 * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or 22 * local coords. 23 */ 24 25 enum GPFlag { 26 kColor_GPFlag = 0x1, 27 kLocalCoord_GPFlag = 0x2, 28 kCoverage_GPFlag= 0x4, 29 }; 30 31 class DefaultGeoProc : public GrGeometryProcessor { 32 public: 33 static sk_sp<GrGeometryProcessor> Make(uint32_t gpTypeFlags, 34 GrColor color, 35 const SkMatrix& viewMatrix, 36 const SkMatrix& localMatrix, 37 bool localCoordsWillBeRead, 38 bool coverageWillBeIgnored, 39 uint8_t coverage) { 40 return sk_sp<GrGeometryProcessor>(new DefaultGeoProc( 41 gpTypeFlags, color, viewMatrix, localMatrix, coverage, 42 localCoordsWillBeRead, coverageWillBeIgnored)); 43 } 44 45 const char* name() const override { return "DefaultGeometryProcessor"; } 46 47 const Attribute* inPosition() const { return fInPosition; } 48 const Attribute* inColor() const { return fInColor; } 49 const Attribute* inLocalCoords() const { return fInLocalCoords; } 50 const Attribute* inCoverage() const { return fInCoverage; } 51 GrColor color() const { return fColor; } 52 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; } 53 bool hasVertexColor() const { return SkToBool(fInColor); } 54 const SkMatrix& viewMatrix() const { return fViewMatrix; } 55 const SkMatrix& localMatrix() const { return fLocalMatrix; } 56 bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; } 57 uint8_t coverage() const { return fCoverage; } 58 bool coverageWillBeIgnored() const { return fCoverageWillBeIgnored; } 59 bool hasVertexCoverage() const { return SkToBool(fInCoverage); } 60 61 class GLSLProcessor : public GrGLSLGeometryProcessor { 62 public: 63 GLSLProcessor() 64 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverage(0xff) {} 65 66 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 67 const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>(); 68 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 69 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 70 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 71 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 72 73 // emit attributes 74 varyingHandler->emitAttributes(gp); 75 76 // Setup pass through color 77 if (!gp.colorIgnored()) { 78 if (gp.hasVertexColor()) { 79 varyingHandler->addPassThroughAttribute(gp.inColor(), args.fOutputColor); 80 } else { 81 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, 82 &fColorUniform); 83 } 84 } 85 86 // Setup position 87 this->setupPosition(vertBuilder, 88 uniformHandler, 89 gpArgs, 90 gp.inPosition()->fName, 91 gp.viewMatrix(), 92 &fViewMatrixUniform); 93 94 if (gp.hasExplicitLocalCoords()) { 95 // emit transforms with explicit local coords 96 this->emitTransforms(vertBuilder, 97 varyingHandler, 98 uniformHandler, 99 gpArgs->fPositionVar, 100 gp.inLocalCoords()->fName, 101 gp.localMatrix(), 102 args.fFPCoordTransformHandler); 103 } else { 104 // emit transforms with position 105 this->emitTransforms(vertBuilder, 106 varyingHandler, 107 uniformHandler, 108 gpArgs->fPositionVar, 109 gp.inPosition()->fName, 110 gp.localMatrix(), 111 args.fFPCoordTransformHandler); 112 } 113 114 // Setup coverage as pass through 115 if (!gp.coverageWillBeIgnored()) { 116 if (gp.hasVertexCoverage()) { 117 fragBuilder->codeAppendf("float alpha = 1.0;"); 118 varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha"); 119 fragBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); 120 } else if (gp.coverage() == 0xff) { 121 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage); 122 } else { 123 const char* fragCoverage; 124 fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 125 kFloat_GrSLType, 126 kDefault_GrSLPrecision, 127 "Coverage", 128 &fragCoverage); 129 fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage); 130 } 131 } 132 } 133 134 static inline void GenKey(const GrGeometryProcessor& gp, 135 const GrGLSLCaps&, 136 GrProcessorKeyBuilder* b) { 137 const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); 138 uint32_t key = def.fFlags; 139 key |= def.colorIgnored() << 8; 140 key |= def.coverageWillBeIgnored() << 9; 141 key |= def.hasVertexColor() << 10; 142 key |= def.hasVertexCoverage() << 11; 143 key |= def.coverage() == 0xff ? 0x1 << 12 : 0; 144 key |= def.localCoordsWillBeRead() && def.localMatrix().hasPerspective() ? 0x1 << 24 : 145 0x0; 146 key |= ComputePosKey(def.viewMatrix()) << 25; 147 b->add32(key); 148 } 149 150 void setData(const GrGLSLProgramDataManager& pdman, 151 const GrPrimitiveProcessor& gp, 152 FPCoordTransformIter&& transformIter) override { 153 const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>(); 154 155 if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) { 156 fViewMatrix = dgp.viewMatrix(); 157 float viewMatrix[3 * 3]; 158 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 159 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 160 } 161 162 if (dgp.color() != fColor && !dgp.hasVertexColor()) { 163 float c[4]; 164 GrColorToRGBAFloat(dgp.color(), c); 165 pdman.set4fv(fColorUniform, 1, c); 166 fColor = dgp.color(); 167 } 168 169 if (!dgp.coverageWillBeIgnored() && 170 dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) { 171 pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage())); 172 fCoverage = dgp.coverage(); 173 } 174 this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter); 175 } 176 177 private: 178 SkMatrix fViewMatrix; 179 GrColor fColor; 180 uint8_t fCoverage; 181 UniformHandle fViewMatrixUniform; 182 UniformHandle fColorUniform; 183 UniformHandle fCoverageUniform; 184 185 typedef GrGLSLGeometryProcessor INHERITED; 186 }; 187 188 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { 189 GLSLProcessor::GenKey(*this, caps, b); 190 } 191 192 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override { 193 return new GLSLProcessor(); 194 } 195 196 private: 197 DefaultGeoProc(uint32_t gpTypeFlags, 198 GrColor color, 199 const SkMatrix& viewMatrix, 200 const SkMatrix& localMatrix, 201 uint8_t coverage, 202 bool localCoordsWillBeRead, 203 bool coverageWillBeIgnored) 204 : fInPosition(nullptr) 205 , fInColor(nullptr) 206 , fInLocalCoords(nullptr) 207 , fInCoverage(nullptr) 208 , fColor(color) 209 , fViewMatrix(viewMatrix) 210 , fLocalMatrix(localMatrix) 211 , fCoverage(coverage) 212 , fFlags(gpTypeFlags) 213 , fLocalCoordsWillBeRead(localCoordsWillBeRead) 214 , fCoverageWillBeIgnored(coverageWillBeIgnored) { 215 this->initClassID<DefaultGeoProc>(); 216 bool hasColor = SkToBool(gpTypeFlags & kColor_GPFlag); 217 bool hasExplicitLocalCoords = SkToBool(gpTypeFlags & kLocalCoord_GPFlag); 218 bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPFlag); 219 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, 220 kHigh_GrSLPrecision); 221 if (hasColor) { 222 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 223 } 224 if (hasExplicitLocalCoords) { 225 fInLocalCoords = &this->addVertexAttrib("inLocalCoord", kVec2f_GrVertexAttribType, 226 kHigh_GrSLPrecision); 227 this->setHasExplicitLocalCoords(); 228 } 229 if (hasCoverage) { 230 fInCoverage = &this->addVertexAttrib("inCoverage", kFloat_GrVertexAttribType); 231 } 232 } 233 234 const Attribute* fInPosition; 235 const Attribute* fInColor; 236 const Attribute* fInLocalCoords; 237 const Attribute* fInCoverage; 238 GrColor fColor; 239 SkMatrix fViewMatrix; 240 SkMatrix fLocalMatrix; 241 uint8_t fCoverage; 242 uint32_t fFlags; 243 bool fLocalCoordsWillBeRead; 244 bool fCoverageWillBeIgnored; 245 246 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 247 248 typedef GrGeometryProcessor INHERITED; 249 }; 250 251 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc); 252 253 sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) { 254 uint32_t flags = 0; 255 if (d->fRandom->nextBool()) { 256 flags |= kColor_GPFlag; 257 } 258 if (d->fRandom->nextBool()) { 259 flags |= kCoverage_GPFlag; 260 } 261 if (d->fRandom->nextBool()) { 262 flags |= kLocalCoord_GPFlag; 263 } 264 265 return DefaultGeoProc::Make(flags, 266 GrRandomColor(d->fRandom), 267 GrTest::TestMatrix(d->fRandom), 268 GrTest::TestMatrix(d->fRandom), 269 d->fRandom->nextBool(), 270 d->fRandom->nextBool(), 271 GrRandomCoverage(d->fRandom)); 272 } 273 274 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color, 275 const Coverage& coverage, 276 const LocalCoords& localCoords, 277 const SkMatrix& viewMatrix) { 278 uint32_t flags = 0; 279 flags |= color.fType == Color::kAttribute_Type ? kColor_GPFlag : 0; 280 flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPFlag : 0; 281 flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPFlag : 0; 282 283 uint8_t inCoverage = coverage.fCoverage; 284 bool coverageWillBeIgnored = coverage.fType == Coverage::kNone_Type; 285 bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type; 286 287 GrColor inColor = color.fColor; 288 return DefaultGeoProc::Make(flags, 289 inColor, 290 viewMatrix, 291 localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), 292 localCoordsWillBeRead, 293 coverageWillBeIgnored, 294 inCoverage); 295 } 296 297 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( 298 const Color& color, 299 const Coverage& coverage, 300 const LocalCoords& localCoords, 301 const SkMatrix& viewMatrix) { 302 SkMatrix invert = SkMatrix::I(); 303 if (LocalCoords::kUnused_Type != localCoords.fType) { 304 SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType); 305 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) { 306 SkDebugf("Could not invert\n"); 307 return nullptr; 308 } 309 310 if (localCoords.hasLocalMatrix()) { 311 invert.preConcat(*localCoords.fMatrix); 312 } 313 } 314 315 LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert); 316 return Make(color, coverage, inverted, SkMatrix::I()); 317 } 318