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 
     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.numTextureSamplers() == 1);
     34         SkDEBUGCODE(GrTexture* atlas = cte.textureSampler(0).texture());
     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.hasVertexColor()) {
     45             varyingHandler->addPassThroughAttribute(cte.inColor(), args.fOutputColor);
     46         } else {
     47             this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
     48                                     &fColorUniform);
     49         }
     50 
     51         // Setup position
     52         this->setupPosition(vertBuilder, gpArgs, cte.inPosition()->fName);
     53 
     54         // emit transforms
     55         this->emitTransforms(vertBuilder,
     56                              varyingHandler,
     57                              uniformHandler,
     58                              gpArgs->fPositionVar,
     59                              cte.inPosition()->fName,
     60                              cte.localMatrix(),
     61                              args.fFPCoordTransformHandler);
     62 
     63         if (cte.maskFormat() == kARGB_GrMaskFormat) {
     64             fragBuilder->codeAppendf("%s = ", args.fOutputColor);
     65             fragBuilder->appendTextureLookupAndModulate(args.fOutputColor,
     66                                                         args.fTexSamplers[0],
     67                                                         v.fsIn(),
     68                                                         kVec2f_GrSLType);
     69             fragBuilder->codeAppend(";");
     70             fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
     71         } else {
     72             fragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
     73             fragBuilder->appendTextureLookup(args.fTexSamplers[0], v.fsIn(), kVec2f_GrSLType);
     74             fragBuilder->codeAppend(";");
     75             if (cte.maskFormat() == kA565_GrMaskFormat) {
     76                 // set alpha to be max of rgb coverage
     77                 fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
     78                                          args.fOutputCoverage, args.fOutputCoverage,
     79                                          args.fOutputCoverage, args.fOutputCoverage);
     80             }
     81         }
     82     }
     83 
     84     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
     85                  FPCoordTransformIter&& transformIter) override {
     86         const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
     87         if (btgp.color() != fColor && !btgp.hasVertexColor()) {
     88             float c[4];
     89             GrColorToRGBAFloat(btgp.color(), c);
     90             pdman.set4fv(fColorUniform, 1, c);
     91             fColor = btgp.color();
     92         }
     93         this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
     94     }
     95 
     96     static inline void GenKey(const GrGeometryProcessor& proc,
     97                               const GrShaderCaps&,
     98                               GrProcessorKeyBuilder* b) {
     99         const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>();
    100         uint32_t key = 0;
    101         key |= (gp.usesLocalCoords() && gp.localMatrix().hasPerspective()) ? 0x1 : 0x0;
    102         key |= gp.maskFormat() << 1;
    103         b->add32(key);
    104 
    105         // Currently we hardcode numbers to convert atlas coordinates to normalized floating point
    106         SkASSERT(gp.numTextureSamplers() == 1);
    107         GrTexture* atlas = gp.textureSampler(0).texture();
    108         SkASSERT(atlas);
    109         b->add32(atlas->width());
    110         b->add32(atlas->height());
    111     }
    112 
    113 private:
    114     GrColor fColor;
    115     UniformHandle fColorUniform;
    116 
    117     typedef GrGLSLGeometryProcessor INHERITED;
    118 };
    119 
    120 ///////////////////////////////////////////////////////////////////////////////
    121 
    122 GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrResourceProvider* resourceProvider, GrColor color,
    123                                          sk_sp<GrTextureProxy> proxy,
    124                                          const GrSamplerParams& params, GrMaskFormat format,
    125                                          const SkMatrix& localMatrix, bool usesLocalCoords)
    126     : fColor(color)
    127     , fLocalMatrix(localMatrix)
    128     , fUsesLocalCoords(usesLocalCoords)
    129     , fTextureSampler(resourceProvider, std::move(proxy), params)
    130     , fInColor(nullptr)
    131     , fMaskFormat(format) {
    132     this->initClassID<GrBitmapTextGeoProc>();
    133     fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType);
    134 
    135     bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
    136                           kA565_GrMaskFormat == fMaskFormat;
    137     if (hasVertexColor) {
    138         fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
    139     }
    140     fInTextureCoords = &this->addVertexAttrib("inTextureCoords",  kVec2us_GrVertexAttribType,
    141                                               kHigh_GrSLPrecision);
    142     this->addTextureSampler(&fTextureSampler);
    143 }
    144 
    145 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
    146                                               GrProcessorKeyBuilder* b) const {
    147     GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
    148 }
    149 
    150 GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrShaderCaps& caps) const {
    151     return new GrGLBitmapTextGeoProc();
    152 }
    153 
    154 ///////////////////////////////////////////////////////////////////////////////
    155 
    156 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
    157 
    158 #if GR_TEST_UTILS
    159 sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
    160     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
    161                                         : GrProcessorUnitTest::kAlphaTextureIdx;
    162     sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
    163 
    164     static const SkShader::TileMode kTileModes[] = {
    165         SkShader::kClamp_TileMode,
    166         SkShader::kRepeat_TileMode,
    167         SkShader::kMirror_TileMode,
    168     };
    169     SkShader::TileMode tileModes[] = {
    170         kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
    171         kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
    172     };
    173     GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode
    174                                                              : GrSamplerParams::kNone_FilterMode);
    175 
    176     GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning
    177     switch (d->fRandom->nextULessThan(3)) {
    178         case 0:
    179             format = kA8_GrMaskFormat;
    180             break;
    181         case 1:
    182             format = kA565_GrMaskFormat;
    183             break;
    184         case 2:
    185             format = kARGB_GrMaskFormat;
    186             break;
    187     }
    188 
    189     return GrBitmapTextGeoProc::Make(d->resourceProvider(), GrRandomColor(d->fRandom),
    190                                      std::move(proxy),
    191                                      params, format, GrTest::TestMatrix(d->fRandom),
    192                                      d->fRandom->nextBool());
    193 }
    194 #endif
    195