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 18class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor { 19public: 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 122private: 123 GrColor fColor; 124 UniformHandle fColorUniform; 125 126 typedef GrGLSLGeometryProcessor INHERITED; 127}; 128 129/////////////////////////////////////////////////////////////////////////////// 130 131GrBitmapTextGeoProc::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 154void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrGLSLCaps& caps, 155 GrProcessorKeyBuilder* b) const { 156 GrGLBitmapTextGeoProc::GenKey(*this, caps, b); 157} 158 159GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrGLSLCaps& caps) const { 160 return new GrGLBitmapTextGeoProc(); 161} 162 163/////////////////////////////////////////////////////////////////////////////// 164 165GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc); 166 167const 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