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