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