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