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 "GrFontAtlasSizes.h" 10#include "GrInvariantOutput.h" 11#include "GrTexture.h" 12#include "gl/GrGLProcessor.h" 13#include "gl/GrGLSL.h" 14#include "gl/GrGLTexture.h" 15#include "gl/GrGLGeometryProcessor.h" 16#include "gl/builders/GrGLProgramBuilder.h" 17 18struct BitmapTextBatchTracker { 19 GrGPInput fInputColorType; 20 GrColor fColor; 21 bool fUsesLocalCoords; 22}; 23 24class GrGLBitmapTextGeoProc : public GrGLGeometryProcessor { 25public: 26 GrGLBitmapTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&) 27 : fColor(GrColor_ILLEGAL) {} 28 29 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 30 const GrBitmapTextGeoProc& cte = args.fGP.cast<GrBitmapTextGeoProc>(); 31 const BitmapTextBatchTracker& local = args.fBT.cast<BitmapTextBatchTracker>(); 32 33 GrGLGPBuilder* pb = args.fPB; 34 GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); 35 36 // emit attributes 37 vsBuilder->emitAttributes(cte); 38 39 GrGLVertToFrag v(kVec2f_GrSLType); 40 pb->addVarying("TextureCoords", &v); 41 // this is only used with text, so our texture bounds always match the glyph atlas 42 if (cte.maskFormat() == kA8_GrMaskFormat) { 43 vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " 44 GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", v.vsOut(), 45 cte.inTextureCoords()->fName); 46 } else { 47 vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_RECIP_WIDTH ", " 48 GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", v.vsOut(), 49 cte.inTextureCoords()->fName); 50 } 51 52 // Setup pass through color 53 this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, cte.inColor(), 54 &fColorUniform); 55 56 // Setup position 57 this->setupPosition(pb, gpArgs, cte.inPosition()->fName); 58 59 // emit transforms 60 this->emitTransforms(args.fPB, gpArgs->fPositionVar, cte.inPosition()->fName, 61 cte.localMatrix(), args.fTransformsIn, args.fTransformsOut); 62 63 GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); 64 if (cte.maskFormat() == kARGB_GrMaskFormat) { 65 fsBuilder->codeAppendf("%s = ", args.fOutputColor); 66 fsBuilder->appendTextureLookupAndModulate(args.fOutputColor, 67 args.fSamplers[0], 68 v.fsIn(), 69 kVec2f_GrSLType); 70 fsBuilder->codeAppend(";"); 71 fsBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage); 72 } else { 73 fsBuilder->codeAppendf("%s = ", args.fOutputCoverage); 74 fsBuilder->appendTextureLookup(args.fSamplers[0], v.fsIn(), kVec2f_GrSLType); 75 fsBuilder->codeAppend(";"); 76 } 77 } 78 79 virtual void setData(const GrGLProgramDataManager& pdman, 80 const GrPrimitiveProcessor& gp, 81 const GrBatchTracker& bt) override { 82 const BitmapTextBatchTracker& local = bt.cast<BitmapTextBatchTracker>(); 83 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 84 GrGLfloat c[4]; 85 GrColorToRGBAFloat(local.fColor, c); 86 pdman.set4fv(fColorUniform, 1, c); 87 fColor = local.fColor; 88 } 89 } 90 91 void setTransformData(const GrPrimitiveProcessor& primProc, 92 const GrGLProgramDataManager& pdman, 93 int index, 94 const SkTArray<const GrCoordTransform*, true>& transforms) override { 95 this->setTransformDataHelper<GrBitmapTextGeoProc>(primProc, pdman, index, transforms); 96 } 97 98 static inline void GenKey(const GrGeometryProcessor& proc, 99 const GrBatchTracker& bt, 100 const GrGLSLCaps&, 101 GrProcessorKeyBuilder* b) { 102 const BitmapTextBatchTracker& local = bt.cast<BitmapTextBatchTracker>(); 103 // We have to put the optional vertex attribute as part of the key. See the comment 104 // on addVertexAttrib. 105 // TODO When we have deferred geometry we can fix this 106 const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>(); 107 uint32_t key = 0; 108 key |= SkToBool(gp.inColor()) ? 0x1 : 0x0; 109 key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x2 : 0x0; 110 key |= gp.maskFormat() == kARGB_GrMaskFormat ? 0x4 : 0x0; 111 b->add32(local.fInputColorType << 16 | key); 112 } 113 114private: 115 GrColor fColor; 116 UniformHandle fColorUniform; 117 118 typedef GrGLGeometryProcessor INHERITED; 119}; 120 121/////////////////////////////////////////////////////////////////////////////// 122 123GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, GrTexture* texture, 124 const GrTextureParams& params, GrMaskFormat format, 125 const SkMatrix& localMatrix) 126 : fColor(color) 127 , fLocalMatrix(localMatrix) 128 , fTextureAccess(texture, params) 129 , fInColor(NULL) 130 , fMaskFormat(format) { 131 this->initClassID<GrBitmapTextGeoProc>(); 132 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType)); 133 134 bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat; 135 if (hasVertexColor) { 136 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 137 } 138 fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 139 kVec2s_GrVertexAttribType)); 140 this->addTextureAccess(&fTextureAccess); 141} 142 143void GrBitmapTextGeoProc::getGLProcessorKey(const GrBatchTracker& bt, 144 const GrGLSLCaps& caps, 145 GrProcessorKeyBuilder* b) const { 146 GrGLBitmapTextGeoProc::GenKey(*this, bt, caps, b); 147} 148 149GrGLPrimitiveProcessor* 150GrBitmapTextGeoProc::createGLInstance(const GrBatchTracker& bt, 151 const GrGLSLCaps& caps) const { 152 return SkNEW_ARGS(GrGLBitmapTextGeoProc, (*this, bt)); 153} 154 155void GrBitmapTextGeoProc::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const { 156 BitmapTextBatchTracker* local = bt->cast<BitmapTextBatchTracker>(); 157 local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, 158 SkToBool(fInColor)); 159 local->fUsesLocalCoords = init.fUsesLocalCoords; 160} 161 162/////////////////////////////////////////////////////////////////////////////// 163 164GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc); 165 166GrGeometryProcessor* GrBitmapTextGeoProc::TestCreate(SkRandom* random, 167 GrContext*, 168 const GrDrawTargetCaps&, 169 GrTexture* textures[]) { 170 int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 171 GrProcessorUnitTest::kAlphaTextureIdx; 172 static const SkShader::TileMode kTileModes[] = { 173 SkShader::kClamp_TileMode, 174 SkShader::kRepeat_TileMode, 175 SkShader::kMirror_TileMode, 176 }; 177 SkShader::TileMode tileModes[] = { 178 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 179 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 180 }; 181 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : 182 GrTextureParams::kNone_FilterMode); 183 184 GrMaskFormat format; 185 switch (random->nextULessThan(3)) { 186 default: 187 SkFAIL("Incomplete enum\n"); 188 case 0: 189 format = kA8_GrMaskFormat; 190 break; 191 case 1: 192 format = kA565_GrMaskFormat; 193 break; 194 case 2: 195 format = kARGB_GrMaskFormat; 196 break; 197 } 198 199 return GrBitmapTextGeoProc::Create(GrRandomColor(random), textures[texIdx], params, 200 format, GrTest::TestMatrix(random)); 201} 202