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 "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