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).peekTexture()); 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 } 76 } 77 78 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp, 79 FPCoordTransformIter&& transformIter) override { 80 const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>(); 81 if (btgp.color() != fColor && !btgp.hasVertexColor()) { 82 float c[4]; 83 GrColorToRGBAFloat(btgp.color(), c); 84 pdman.set4fv(fColorUniform, 1, c); 85 fColor = btgp.color(); 86 } 87 this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter); 88 } 89 90 static inline void GenKey(const GrGeometryProcessor& proc, 91 const GrShaderCaps&, 92 GrProcessorKeyBuilder* b) { 93 const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>(); 94 uint32_t key = 0; 95 key |= (gp.usesLocalCoords() && gp.localMatrix().hasPerspective()) ? 0x1 : 0x0; 96 key |= gp.maskFormat() << 1; 97 b->add32(key); 98 99 // Currently we hardcode numbers to convert atlas coordinates to normalized floating point 100 SkASSERT(gp.numTextureSamplers() == 1); 101 GrTextureProxy* atlas = gp.textureSampler(0).proxy(); 102 if (atlas) { 103 b->add32(atlas->width()); 104 b->add32(atlas->height()); 105 } 106 } 107 108 private: 109 GrColor fColor; 110 UniformHandle fColorUniform; 111 112 typedef GrGLSLGeometryProcessor INHERITED; 113 }; 114 115 /////////////////////////////////////////////////////////////////////////////// 116 117 GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, 118 sk_sp<GrTextureProxy> proxy, 119 const GrSamplerParams& params, GrMaskFormat format, 120 const SkMatrix& localMatrix, bool usesLocalCoords) 121 : fColor(color) 122 , fLocalMatrix(localMatrix) 123 , fUsesLocalCoords(usesLocalCoords) 124 , fTextureSampler(std::move(proxy), params) 125 , fInColor(nullptr) 126 , fMaskFormat(format) { 127 this->initClassID<GrBitmapTextGeoProc>(); 128 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType); 129 130 bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat || 131 kA565_GrMaskFormat == fMaskFormat; 132 if (hasVertexColor) { 133 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 134 } 135 fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kVec2us_GrVertexAttribType, 136 kHigh_GrSLPrecision); 137 this->addTextureSampler(&fTextureSampler); 138 } 139 140 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps, 141 GrProcessorKeyBuilder* b) const { 142 GrGLBitmapTextGeoProc::GenKey(*this, caps, b); 143 } 144 145 GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrShaderCaps& caps) const { 146 return new GrGLBitmapTextGeoProc(); 147 } 148 149 /////////////////////////////////////////////////////////////////////////////// 150 151 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc); 152 153 #if GR_TEST_UTILS 154 sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) { 155 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx 156 : GrProcessorUnitTest::kAlphaTextureIdx; 157 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx); 158 159 static const SkShader::TileMode kTileModes[] = { 160 SkShader::kClamp_TileMode, 161 SkShader::kRepeat_TileMode, 162 SkShader::kMirror_TileMode, 163 }; 164 SkShader::TileMode tileModes[] = { 165 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 166 kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 167 }; 168 GrSamplerParams params(tileModes, d->fRandom->nextBool() ? GrSamplerParams::kBilerp_FilterMode 169 : GrSamplerParams::kNone_FilterMode); 170 171 GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning 172 switch (d->fRandom->nextULessThan(3)) { 173 case 0: 174 format = kA8_GrMaskFormat; 175 break; 176 case 1: 177 format = kA565_GrMaskFormat; 178 break; 179 case 2: 180 format = kARGB_GrMaskFormat; 181 break; 182 } 183 184 return GrBitmapTextGeoProc::Make(GrRandomColor(d->fRandom), std::move(proxy), 185 params, format, GrTest::TestMatrix(d->fRandom), 186 d->fRandom->nextBool()); 187 } 188 #endif 189