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