Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2013 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 "GrBitmapTextGeoProc.h"
      9 #include "GrInvariantOutput.h"
     10 #include "GrTexture.h"
     11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     12 #include "glsl/GrGLSLGeometryProcessor.h"
     13 #include "glsl/GrGLSLProgramDataManager.h"
     14 #include "glsl/GrGLSLUniformHandler.h"
     15 #include "glsl/GrGLSLVarying.h"
     16 #include "glsl/GrGLSLVertexShaderBuilder.h"
     17 
     18 class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor {
     19 public:
     20     GrGLBitmapTextGeoProc() : fColor(GrColor_ILLEGAL) {}
     21 
     22     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
     23         const GrBitmapTextGeoProc& cte = args.fGP.cast<GrBitmapTextGeoProc>();
     24 
     25         GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
     26         GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
     27         GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     28 
     29         // emit attributes
     30         varyingHandler->emitAttributes(cte);
     31 
     32         // compute numbers to be hardcoded to convert texture coordinates from int to float
     33         SkASSERT(cte.numTextures() == 1);
     34         SkDEBUGCODE(GrTexture* atlas = cte.textureAccess(0).getTexture());
     35         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
     36 
     37         GrGLSLVertToFrag v(kVec2f_GrSLType);
     38         varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
     39         vertBuilder->codeAppendf("%s = %s;", v.vsOut(),
     40                                  cte.inTextureCoords()->fName);
     41 
     42         GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
     43         // Setup pass through color
     44         if (!cte.colorIgnored()) {
     45             if (cte.hasVertexColor()) {
     46                 varyingHandler->addPassThroughAttribute(cte.inColor(), args.fOutputColor);
     47             } else {
     48                 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
     49                                         &fColorUniform);
     50             }
     51         }
     52 
     53         // Setup position
     54         this->setupPosition(vertBuilder, gpArgs, cte.inPosition()->fName);
     55 
     56         // emit transforms
     57         this->emitTransforms(vertBuilder,
     58                              varyingHandler,
     59                              uniformHandler,
     60                              gpArgs->fPositionVar,
     61                              cte.inPosition()->fName,
     62                              cte.localMatrix(),
     63                              args.fTransformsIn,
     64                              args.fTransformsOut);
     65 
     66         if (cte.maskFormat() == kARGB_GrMaskFormat) {
     67             fragBuilder->codeAppendf("%s = ", args.fOutputColor);
     68             fragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
     69                                                         args.fSamplers[0],
     70                                                         v.fsIn(),
     71                                                         kVec2f_GrSLType);
     72             fragBuilder->codeAppend(";");
     73             fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
     74         } else {
     75             fragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
     76             fragBuilder->appendTextureLookup(args.fSamplers[0], v.fsIn(), kVec2f_GrSLType);
     77             fragBuilder->codeAppend(";");
     78             if (cte.maskFormat() == kA565_GrMaskFormat) {
     79                 // set alpha to be max of rgb coverage
     80                 fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
     81                                          args.fOutputCoverage, args.fOutputCoverage,
     82                                          args.fOutputCoverage, args.fOutputCoverage);
     83             }
     84         }
     85     }
     86 
     87     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp) override {
     88         const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
     89         if (btgp.color() != fColor && !btgp.hasVertexColor()) {
     90             float c[4];
     91             GrColorToRGBAFloat(btgp.color(), c);
     92             pdman.set4fv(fColorUniform, 1, c);
     93             fColor = btgp.color();
     94         }
     95     }
     96 
     97     void setTransformData(const GrPrimitiveProcessor& primProc,
     98                           const GrGLSLProgramDataManager& pdman,
     99                           int index,
    100                           const SkTArray<const GrCoordTransform*, true>& transforms) override {
    101         this->setTransformDataHelper<GrBitmapTextGeoProc>(primProc, pdman, index, transforms);
    102     }
    103 
    104     static inline void GenKey(const GrGeometryProcessor& proc,
    105                               const GrGLSLCaps&,
    106                               GrProcessorKeyBuilder* b) {
    107         const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>();
    108         uint32_t key = 0;
    109         key |= gp.usesLocalCoords() && gp.localMatrix().hasPerspective() ? 0x1 : 0x0;
    110         key |= gp.colorIgnored() ? 0x2 : 0x0;
    111         key |= gp.maskFormat() << 3;
    112         b->add32(key);
    113 
    114         // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
    115         SkASSERT(gp.numTextures() == 1);
    116         GrTexture* atlas = gp.textureAccess(0).getTexture();
    117         SkASSERT(atlas);
    118         b->add32(atlas->width());
    119         b->add32(atlas->height());
    120     }
    121 
    122 private:
    123     GrColor fColor;
    124     UniformHandle fColorUniform;
    125 
    126     typedef GrGLSLGeometryProcessor INHERITED;
    127 };
    128 
    129 ///////////////////////////////////////////////////////////////////////////////
    130 
    131 GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, GrTexture* texture,
    132                                          const GrTextureParams& params, GrMaskFormat format,
    133                                          const SkMatrix& localMatrix, bool usesLocalCoords)
    134     : fColor(color)
    135     , fLocalMatrix(localMatrix)
    136     , fUsesLocalCoords(usesLocalCoords)
    137     , fTextureAccess(texture, params)
    138     , fInColor(nullptr)
    139     , fMaskFormat(format) {
    140     this->initClassID<GrBitmapTextGeoProc>();
    141     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
    142 
    143     bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
    144                           kA565_GrMaskFormat == fMaskFormat;
    145     if (hasVertexColor) {
    146         fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
    147     }
    148     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
    149                                                         kVec2us_GrVertexAttribType,
    150                                                         kHigh_GrSLPrecision));
    151     this->addTextureAccess(&fTextureAccess);
    152 }
    153 
    154 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrGLSLCaps& caps,
    155                                               GrProcessorKeyBuilder* b) const {
    156     GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
    157 }
    158 
    159 GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrGLSLCaps& caps) const {
    160     return new GrGLBitmapTextGeoProc();
    161 }
    162 
    163 ///////////////////////////////////////////////////////////////////////////////
    164 
    165 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
    166 
    167 const GrGeometryProcessor* GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
    168     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
    169                                           GrProcessorUnitTest::kAlphaTextureIdx;
    170     static const SkShader::TileMode kTileModes[] = {
    171         SkShader::kClamp_TileMode,
    172         SkShader::kRepeat_TileMode,
    173         SkShader::kMirror_TileMode,
    174     };
    175     SkShader::TileMode tileModes[] = {
    176         kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
    177         kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
    178     };
    179     GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode :
    180                                                            GrTextureParams::kNone_FilterMode);
    181 
    182     GrMaskFormat format;
    183     switch (d->fRandom->nextULessThan(3)) {
    184         case 0:
    185             format = kA8_GrMaskFormat;
    186             break;
    187         case 1:
    188             format = kA565_GrMaskFormat;
    189             break;
    190         case 2:
    191             format = kARGB_GrMaskFormat;
    192             break;
    193     }
    194 
    195     return GrBitmapTextGeoProc::Create(GrRandomColor(d->fRandom), d->fTextures[texIdx], params,
    196                                        format, GrTest::TestMatrix(d->fRandom),
    197                                        d->fRandom->nextBool());
    198 }
    199