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 "SkRefCnt.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 kColorAttribute_GPFlag = 0x1, 26 kColorAttributeIsSkColor_GPFlag = 0x2, 27 kLocalCoordAttribute_GPFlag = 0x4, 28 kCoverageAttribute_GPFlag = 0x8, 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 uint8_t coverage) { 39 return sk_sp<GrGeometryProcessor>(new DefaultGeoProc( 40 gpTypeFlags, color, viewMatrix, localMatrix, coverage, localCoordsWillBeRead)); 41 } 42 43 const char* name() const override { return "DefaultGeometryProcessor"; } 44 45 const Attribute* inPosition() const { return fInPosition; } 46 const Attribute* inColor() const { return fInColor; } 47 const Attribute* inLocalCoords() const { return fInLocalCoords; } 48 const Attribute* inCoverage() const { return fInCoverage; } 49 GrColor color() const { return fColor; } 50 bool hasVertexColor() const { return SkToBool(fInColor); } 51 const SkMatrix& viewMatrix() const { return fViewMatrix; } 52 const SkMatrix& localMatrix() const { return fLocalMatrix; } 53 bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; } 54 uint8_t coverage() const { return fCoverage; } 55 bool hasVertexCoverage() const { return SkToBool(fInCoverage); } 56 57 class GLSLProcessor : public GrGLSLGeometryProcessor { 58 public: 59 GLSLProcessor() 60 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverage(0xff) {} 61 62 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 63 const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>(); 64 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 65 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 66 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 67 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 68 69 // emit attributes 70 varyingHandler->emitAttributes(gp); 71 72 // Setup pass through color 73 if (gp.hasVertexColor()) { 74 GrGLSLVertToFrag varying(kVec4f_GrSLType); 75 varyingHandler->addVarying("color", &varying); 76 if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) { 77 // Do a red/blue swap and premul the color. 78 vertBuilder->codeAppendf("%s = vec4(%s.a*%s.bgr, %s.a);", varying.vsOut(), 79 gp.inColor()->fName, gp.inColor()->fName, 80 gp.inColor()->fName); 81 } else { 82 vertBuilder->codeAppendf("%s = %s;\n", varying.vsOut(), gp.inColor()->fName); 83 } 84 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn()); 85 } else { 86 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, 87 &fColorUniform); 88 } 89 90 // Setup position 91 this->setupPosition(vertBuilder, 92 uniformHandler, 93 gpArgs, 94 gp.inPosition()->fName, 95 gp.viewMatrix(), 96 &fViewMatrixUniform); 97 98 if (gp.hasExplicitLocalCoords()) { 99 // emit transforms with explicit local coords 100 this->emitTransforms(vertBuilder, 101 varyingHandler, 102 uniformHandler, 103 gpArgs->fPositionVar, 104 gp.inLocalCoords()->fName, 105 gp.localMatrix(), 106 args.fFPCoordTransformHandler); 107 } else { 108 // emit transforms with position 109 this->emitTransforms(vertBuilder, 110 varyingHandler, 111 uniformHandler, 112 gpArgs->fPositionVar, 113 gp.inPosition()->fName, 114 gp.localMatrix(), 115 args.fFPCoordTransformHandler); 116 } 117 118 // Setup coverage as pass through 119 if (gp.hasVertexCoverage()) { 120 fragBuilder->codeAppendf("float alpha = 1.0;"); 121 varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha"); 122 fragBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); 123 } else if (gp.coverage() == 0xff) { 124 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage); 125 } else { 126 const char* fragCoverage; 127 fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, 128 kFloat_GrSLType, 129 kDefault_GrSLPrecision, 130 "Coverage", 131 &fragCoverage); 132 fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage); 133 } 134 } 135 136 static inline void GenKey(const GrGeometryProcessor& gp, 137 const GrShaderCaps&, 138 GrProcessorKeyBuilder* b) { 139 const DefaultGeoProc& def = gp.cast<DefaultGeoProc>(); 140 uint32_t key = def.fFlags; 141 key |= (def.coverage() == 0xff) ? 0x10 : 0; 142 key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0; 143 key |= ComputePosKey(def.viewMatrix()) << 20; 144 b->add32(key); 145 } 146 147 void setData(const GrGLSLProgramDataManager& pdman, 148 const GrPrimitiveProcessor& gp, 149 FPCoordTransformIter&& transformIter) override { 150 const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>(); 151 152 if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) { 153 fViewMatrix = dgp.viewMatrix(); 154 float viewMatrix[3 * 3]; 155 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 156 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 157 } 158 159 if (dgp.color() != fColor && !dgp.hasVertexColor()) { 160 float c[4]; 161 GrColorToRGBAFloat(dgp.color(), c); 162 pdman.set4fv(fColorUniform, 1, c); 163 fColor = dgp.color(); 164 } 165 166 if (dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) { 167 pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage())); 168 fCoverage = dgp.coverage(); 169 } 170 this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter); 171 } 172 173 private: 174 SkMatrix fViewMatrix; 175 GrColor fColor; 176 uint8_t fCoverage; 177 UniformHandle fViewMatrixUniform; 178 UniformHandle fColorUniform; 179 UniformHandle fCoverageUniform; 180 181 typedef GrGLSLGeometryProcessor INHERITED; 182 }; 183 184 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 185 GLSLProcessor::GenKey(*this, caps, b); 186 } 187 188 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 189 return new GLSLProcessor(); 190 } 191 192 private: 193 DefaultGeoProc(uint32_t gpTypeFlags, 194 GrColor color, 195 const SkMatrix& viewMatrix, 196 const SkMatrix& localMatrix, 197 uint8_t coverage, 198 bool localCoordsWillBeRead) 199 : fColor(color) 200 , fViewMatrix(viewMatrix) 201 , fLocalMatrix(localMatrix) 202 , fCoverage(coverage) 203 , fFlags(gpTypeFlags) 204 , fLocalCoordsWillBeRead(localCoordsWillBeRead) { 205 this->initClassID<DefaultGeoProc>(); 206 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, 207 kHigh_GrSLPrecision); 208 if (fFlags & kColorAttribute_GPFlag) { 209 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 210 } 211 if (fFlags & kLocalCoordAttribute_GPFlag) { 212 fInLocalCoords = &this->addVertexAttrib("inLocalCoord", kVec2f_GrVertexAttribType, 213 kHigh_GrSLPrecision); 214 this->setHasExplicitLocalCoords(); 215 } 216 if (fFlags & kCoverageAttribute_GPFlag) { 217 fInCoverage = &this->addVertexAttrib("inCoverage", kFloat_GrVertexAttribType); 218 } 219 } 220 221 const Attribute* fInPosition = nullptr; 222 const Attribute* fInColor = nullptr; 223 const Attribute* fInLocalCoords = nullptr; 224 const Attribute* fInCoverage = nullptr; 225 GrColor fColor; 226 SkMatrix fViewMatrix; 227 SkMatrix fLocalMatrix; 228 uint8_t fCoverage; 229 uint32_t fFlags; 230 bool fLocalCoordsWillBeRead; 231 232 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 233 234 typedef GrGeometryProcessor INHERITED; 235 }; 236 237 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc); 238 239 #if GR_TEST_UTILS 240 sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) { 241 uint32_t flags = 0; 242 if (d->fRandom->nextBool()) { 243 flags |= kColorAttribute_GPFlag; 244 } 245 if (d->fRandom->nextBool()) { 246 flags |= kColorAttributeIsSkColor_GPFlag; 247 } 248 if (d->fRandom->nextBool()) { 249 flags |= kCoverageAttribute_GPFlag; 250 } 251 if (d->fRandom->nextBool()) { 252 flags |= kLocalCoordAttribute_GPFlag; 253 } 254 255 return DefaultGeoProc::Make(flags, 256 GrRandomColor(d->fRandom), 257 GrTest::TestMatrix(d->fRandom), 258 GrTest::TestMatrix(d->fRandom), 259 260 d->fRandom->nextBool(), 261 GrRandomCoverage(d->fRandom)); 262 } 263 #endif 264 265 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color, 266 const Coverage& coverage, 267 const LocalCoords& localCoords, 268 const SkMatrix& viewMatrix) { 269 uint32_t flags = 0; 270 if (Color::kPremulGrColorAttribute_Type == color.fType) { 271 flags |= kColorAttribute_GPFlag; 272 } else if (Color::kUnpremulSkColorAttribute_Type == color.fType) { 273 flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag; 274 } 275 flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0; 276 flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0; 277 278 uint8_t inCoverage = coverage.fCoverage; 279 bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type; 280 281 GrColor inColor = color.fColor; 282 return DefaultGeoProc::Make(flags, 283 inColor, 284 viewMatrix, 285 localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(), 286 localCoordsWillBeRead, 287 inCoverage); 288 } 289 290 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( 291 const Color& color, 292 const Coverage& coverage, 293 const LocalCoords& localCoords, 294 const SkMatrix& viewMatrix) { 295 SkMatrix invert = SkMatrix::I(); 296 if (LocalCoords::kUnused_Type != localCoords.fType) { 297 SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType); 298 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) { 299 SkDebugf("Could not invert\n"); 300 return nullptr; 301 } 302 303 if (localCoords.hasLocalMatrix()) { 304 invert.preConcat(*localCoords.fMatrix); 305 } 306 } 307 308 LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert); 309 return Make(color, coverage, inverted, SkMatrix::I()); 310 } 311