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 "GrCaps.h"
     11 #include "SkRefCnt.h"
     12 #include "glsl/GrGLSLColorSpaceXformHelper.h"
     13 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     14 #include "glsl/GrGLSLGeometryProcessor.h"
     15 #include "glsl/GrGLSLVertexGeoBuilder.h"
     16 #include "glsl/GrGLSLVarying.h"
     17 #include "glsl/GrGLSLUniformHandler.h"
     18 #include "glsl/GrGLSLUtil.h"
     19 
     20 /*
     21  * The default Geometry Processor simply takes position and multiplies it by the uniform view
     22  * matrix. It also leaves coverage untouched.  Behind the scenes, we may add per vertex color or
     23  * local coords.
     24  */
     25 
     26 enum GPFlag {
     27     kColorAttribute_GPFlag          = 0x1,
     28     kColorAttributeIsSkColor_GPFlag = 0x2,
     29     kColorAttributeIsWide_GPFlag    = 0x4,
     30     kLocalCoordAttribute_GPFlag     = 0x8,
     31     kCoverageAttribute_GPFlag       = 0x10,
     32     kCoverageAttributeTweak_GPFlag  = 0x20,
     33 };
     34 
     35 class DefaultGeoProc : public GrGeometryProcessor {
     36 public:
     37     static sk_sp<GrGeometryProcessor> Make(const GrShaderCaps* shaderCaps,
     38                                            uint32_t gpTypeFlags,
     39                                            const SkPMColor4f& color,
     40                                            sk_sp<GrColorSpaceXform> colorSpaceXform,
     41                                            const SkMatrix& viewMatrix,
     42                                            const SkMatrix& localMatrix,
     43                                            bool localCoordsWillBeRead,
     44                                            uint8_t coverage) {
     45         return sk_sp<GrGeometryProcessor>(new DefaultGeoProc(
     46                 shaderCaps, gpTypeFlags, color, std::move(colorSpaceXform), viewMatrix, localMatrix,
     47                 coverage, localCoordsWillBeRead));
     48     }
     49 
     50     const char* name() const override { return "DefaultGeometryProcessor"; }
     51 
     52     const SkPMColor4f& color() const { return fColor; }
     53     bool hasVertexColor() const { return fInColor.isInitialized(); }
     54     const SkMatrix& viewMatrix() const { return fViewMatrix; }
     55     const SkMatrix& localMatrix() const { return fLocalMatrix; }
     56     bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
     57     uint8_t coverage() const { return fCoverage; }
     58     bool hasVertexCoverage() const { return fInCoverage.isInitialized(); }
     59 
     60     class GLSLProcessor : public GrGLSLGeometryProcessor {
     61     public:
     62         GLSLProcessor()
     63             : fViewMatrix(SkMatrix::InvalidMatrix())
     64             , fColor(SK_PMColor4fILLEGAL)
     65             , fCoverage(0xff) {}
     66 
     67         void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
     68             const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
     69             GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
     70             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     71             GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
     72             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     73 
     74             // emit attributes
     75             varyingHandler->emitAttributes(gp);
     76 
     77             bool tweakAlpha = SkToBool(gp.fFlags & kCoverageAttributeTweak_GPFlag);
     78             SkASSERT(!tweakAlpha || gp.hasVertexCoverage());
     79 
     80             // Setup pass through color
     81             if (gp.hasVertexColor() || tweakAlpha) {
     82                 GrGLSLVarying varying(kHalf4_GrSLType);
     83                 varyingHandler->addVarying("color", &varying);
     84 
     85                 // There are several optional steps to process the color. Start with the attribute,
     86                 // or with uniform color (in the case of folding coverage into a uniform color):
     87                 if (gp.hasVertexColor()) {
     88                     vertBuilder->codeAppendf("half4 color = %s;", gp.fInColor.name());
     89                 } else {
     90                     const char* colorUniformName;
     91                     fColorUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
     92                                                                kHalf4_GrSLType,
     93                                                                "Color",
     94                                                                &colorUniformName);
     95                     vertBuilder->codeAppendf("half4 color = %s;", colorUniformName);
     96                 }
     97 
     98                 // For SkColor, do a red/blue swap, possible color space conversion, and premul
     99                 if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
    100                     vertBuilder->codeAppend("color = color.bgra;");
    101 
    102                     if (gp.fColorSpaceXform) {
    103                         fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
    104                                                    kVertex_GrShaderFlag);
    105                         SkString xformedColor;
    106                         vertBuilder->appendColorGamutXform(&xformedColor, "color",
    107                                                            &fColorSpaceHelper);
    108                         vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
    109                     }
    110 
    111                     vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
    112                 }
    113 
    114                 // Optionally fold coverage into alpha (color).
    115                 if (tweakAlpha) {
    116                     vertBuilder->codeAppendf("color = color * %s;", gp.fInCoverage.name());
    117                 }
    118                 vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
    119                 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
    120             } else {
    121                 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
    122                                         &fColorUniform);
    123             }
    124 
    125             // Setup position
    126             this->writeOutputPosition(vertBuilder,
    127                                       uniformHandler,
    128                                       gpArgs,
    129                                       gp.fInPosition.name(),
    130                                       gp.viewMatrix(),
    131                                       &fViewMatrixUniform);
    132 
    133             if (gp.fInLocalCoords.isInitialized()) {
    134                 // emit transforms with explicit local coords
    135                 this->emitTransforms(vertBuilder,
    136                                      varyingHandler,
    137                                      uniformHandler,
    138                                      gp.fInLocalCoords.asShaderVar(),
    139                                      gp.localMatrix(),
    140                                      args.fFPCoordTransformHandler);
    141             } else {
    142                 // emit transforms with position
    143                 this->emitTransforms(vertBuilder,
    144                                      varyingHandler,
    145                                      uniformHandler,
    146                                      gp.fInPosition.asShaderVar(),
    147                                      gp.localMatrix(),
    148                                      args.fFPCoordTransformHandler);
    149             }
    150 
    151             // Setup coverage as pass through
    152             if (gp.hasVertexCoverage() && !tweakAlpha) {
    153                 fragBuilder->codeAppendf("half alpha = 1.0;");
    154                 varyingHandler->addPassThroughAttribute(gp.fInCoverage, "alpha");
    155                 fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
    156             } else if (gp.coverage() == 0xff) {
    157                 fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
    158             } else {
    159                 const char* fragCoverage;
    160                 fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
    161                                                               kHalf_GrSLType,
    162                                                               "Coverage",
    163                                                               &fragCoverage);
    164                 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, fragCoverage);
    165             }
    166         }
    167 
    168         static inline void GenKey(const GrGeometryProcessor& gp,
    169                                   const GrShaderCaps&,
    170                                   GrProcessorKeyBuilder* b) {
    171             const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
    172             uint32_t key = def.fFlags;
    173             key |= (def.coverage() == 0xff) ? 0x80 : 0;
    174             key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0;
    175             key |= ComputePosKey(def.viewMatrix()) << 20;
    176             b->add32(key);
    177             b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get()));
    178         }
    179 
    180         void setData(const GrGLSLProgramDataManager& pdman,
    181                      const GrPrimitiveProcessor& gp,
    182                      FPCoordTransformIter&& transformIter) override {
    183             const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
    184 
    185             if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) {
    186                 fViewMatrix = dgp.viewMatrix();
    187                 float viewMatrix[3 * 3];
    188                 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
    189                 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
    190             }
    191 
    192             if (!dgp.hasVertexColor() && dgp.color() != fColor) {
    193                 pdman.set4fv(fColorUniform, 1, dgp.color().vec());
    194                 fColor = dgp.color();
    195             }
    196 
    197             if (dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) {
    198                 pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
    199                 fCoverage = dgp.coverage();
    200             }
    201             this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter);
    202 
    203             fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get());
    204         }
    205 
    206     private:
    207         SkMatrix fViewMatrix;
    208         SkPMColor4f fColor;
    209         uint8_t fCoverage;
    210         UniformHandle fViewMatrixUniform;
    211         UniformHandle fColorUniform;
    212         UniformHandle fCoverageUniform;
    213         GrGLSLColorSpaceXformHelper fColorSpaceHelper;
    214 
    215         typedef GrGLSLGeometryProcessor INHERITED;
    216     };
    217 
    218     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
    219         GLSLProcessor::GenKey(*this, caps, b);
    220     }
    221 
    222     GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
    223         return new GLSLProcessor();
    224     }
    225 
    226 private:
    227     DefaultGeoProc(const GrShaderCaps* shaderCaps,
    228                    uint32_t gpTypeFlags,
    229                    const SkPMColor4f& color,
    230                    sk_sp<GrColorSpaceXform> colorSpaceXform,
    231                    const SkMatrix& viewMatrix,
    232                    const SkMatrix& localMatrix,
    233                    uint8_t coverage,
    234                    bool localCoordsWillBeRead)
    235             : INHERITED(kDefaultGeoProc_ClassID)
    236             , fColor(color)
    237             , fViewMatrix(viewMatrix)
    238             , fLocalMatrix(localMatrix)
    239             , fCoverage(coverage)
    240             , fFlags(gpTypeFlags)
    241             , fLocalCoordsWillBeRead(localCoordsWillBeRead)
    242             , fColorSpaceXform(std::move(colorSpaceXform)) {
    243         fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
    244         if (fFlags & kColorAttribute_GPFlag) {
    245             fInColor = MakeColorAttribute("inColor",
    246                                           SkToBool(fFlags & kColorAttributeIsWide_GPFlag));
    247         }
    248         if (fFlags & kLocalCoordAttribute_GPFlag) {
    249             fInLocalCoords = {"inLocalCoord", kFloat2_GrVertexAttribType,
    250                                               kFloat2_GrSLType};
    251         }
    252         if (fFlags & kCoverageAttribute_GPFlag) {
    253             fInCoverage = {"inCoverage", kFloat_GrVertexAttribType, kHalf_GrSLType};
    254         }
    255         this->setVertexAttributes(&fInPosition, 4);
    256     }
    257 
    258     Attribute fInPosition;
    259     Attribute fInColor;
    260     Attribute fInLocalCoords;
    261     Attribute fInCoverage;
    262     SkPMColor4f fColor;
    263     SkMatrix fViewMatrix;
    264     SkMatrix fLocalMatrix;
    265     uint8_t fCoverage;
    266     uint32_t fFlags;
    267     bool fLocalCoordsWillBeRead;
    268     sk_sp<GrColorSpaceXform> fColorSpaceXform;
    269 
    270     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
    271 
    272     typedef GrGeometryProcessor INHERITED;
    273 };
    274 
    275 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
    276 
    277 #if GR_TEST_UTILS
    278 sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
    279     uint32_t flags = 0;
    280     if (d->fRandom->nextBool()) {
    281         flags |= kColorAttribute_GPFlag;
    282     }
    283     if (d->fRandom->nextBool()) {
    284         flags |= kColorAttributeIsSkColor_GPFlag;
    285     }
    286     if (d->fRandom->nextBool()) {
    287         flags |= kColorAttributeIsWide_GPFlag;
    288     }
    289     if (d->fRandom->nextBool()) {
    290         flags |= kCoverageAttribute_GPFlag;
    291         if (d->fRandom->nextBool()) {
    292             flags |= kCoverageAttributeTweak_GPFlag;
    293         }
    294     }
    295     if (d->fRandom->nextBool()) {
    296         flags |= kLocalCoordAttribute_GPFlag;
    297     }
    298 
    299     return DefaultGeoProc::Make(d->caps()->shaderCaps(),
    300                                 flags,
    301                                 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
    302                                 GrTest::TestColorXform(d->fRandom),
    303                                 GrTest::TestMatrix(d->fRandom),
    304                                 GrTest::TestMatrix(d->fRandom),
    305                                 d->fRandom->nextBool(),
    306                                 GrRandomCoverage(d->fRandom));
    307 }
    308 #endif
    309 
    310 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const GrShaderCaps* shaderCaps,
    311                                                          const Color& color,
    312                                                          const Coverage& coverage,
    313                                                          const LocalCoords& localCoords,
    314                                                          const SkMatrix& viewMatrix) {
    315     uint32_t flags = 0;
    316     if (Color::kPremulGrColorAttribute_Type == color.fType) {
    317         flags |= kColorAttribute_GPFlag;
    318     } else if (Color::kUnpremulSkColorAttribute_Type == color.fType) {
    319         flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag;
    320     } else if (Color::kPremulWideColorAttribute_Type == color.fType) {
    321         flags |= kColorAttribute_GPFlag | kColorAttributeIsWide_GPFlag;
    322     }
    323     if (Coverage::kAttribute_Type == coverage.fType) {
    324         flags |= kCoverageAttribute_GPFlag;
    325     } else if (Coverage::kAttributeTweakAlpha_Type == coverage.fType) {
    326         flags |= kCoverageAttribute_GPFlag | kCoverageAttributeTweak_GPFlag;
    327     }
    328     flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
    329 
    330     uint8_t inCoverage = coverage.fCoverage;
    331     bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
    332 
    333     return DefaultGeoProc::Make(shaderCaps,
    334                                 flags,
    335                                 color.fColor,
    336                                 color.fColorSpaceXform,
    337                                 viewMatrix,
    338                                 localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
    339                                 localCoordsWillBeRead,
    340                                 inCoverage);
    341 }
    342 
    343 sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
    344                                                                      const GrShaderCaps* shaderCaps,
    345                                                                      const Color& color,
    346                                                                      const Coverage& coverage,
    347                                                                      const LocalCoords& localCoords,
    348                                                                      const SkMatrix& viewMatrix) {
    349     SkMatrix invert = SkMatrix::I();
    350     if (LocalCoords::kUnused_Type != localCoords.fType) {
    351         SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
    352         if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
    353             return nullptr;
    354         }
    355 
    356         if (localCoords.hasLocalMatrix()) {
    357             invert.postConcat(*localCoords.fMatrix);
    358         }
    359     }
    360 
    361     LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
    362     return Make(shaderCaps, color, coverage, inverted, SkMatrix::I());
    363 }
    364