Home | History | Annotate | Download | only in gpu
      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