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 "src/gpu/effects/GrBitmapTextGeoProc.h" 9 10#include "src/gpu/GrCaps.h" 11#include "src/gpu/GrShaderCaps.h" 12#include "src/gpu/GrTexture.h" 13#include "src/gpu/effects/GrAtlasedShaderHelpers.h" 14#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 15#include "src/gpu/glsl/GrGLSLProgramDataManager.h" 16#include "src/gpu/glsl/GrGLSLUniformHandler.h" 17#include "src/gpu/glsl/GrGLSLVarying.h" 18#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" 19 20class GrBitmapTextGeoProc::Impl : public ProgramImpl { 21public: 22 void setData(const GrGLSLProgramDataManager& pdman, 23 const GrShaderCaps& shaderCaps, 24 const GrGeometryProcessor& geomProc) override { 25 const GrBitmapTextGeoProc& btgp = geomProc.cast<GrBitmapTextGeoProc>(); 26 if (btgp.fColor != fColor && !btgp.hasVertexColor()) { 27 pdman.set4fv(fColorUniform, 1, btgp.fColor.vec()); 28 fColor = btgp.fColor; 29 } 30 31 const SkISize& atlasDimensions = btgp.fAtlasDimensions; 32 SkASSERT(SkIsPow2(atlasDimensions.fWidth) && SkIsPow2(atlasDimensions.fHeight)); 33 34 if (fAtlasDimensions != atlasDimensions) { 35 pdman.set2f(fAtlasDimensionsInvUniform, 36 1.0f / atlasDimensions.fWidth, 37 1.0f / atlasDimensions.fHeight); 38 fAtlasDimensions = atlasDimensions; 39 } 40 41 SetTransform(pdman, shaderCaps, fLocalMatrixUniform, btgp.fLocalMatrix, &fLocalMatrix); 42 } 43 44private: 45 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 46 const GrBitmapTextGeoProc& btgp = args.fGeomProc.cast<GrBitmapTextGeoProc>(); 47 48 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 49 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 50 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 51 52 // emit attributes 53 varyingHandler->emitAttributes(btgp); 54 55 const char* atlasDimensionsInvName; 56 fAtlasDimensionsInvUniform = uniformHandler->addUniform(nullptr, kVertex_GrShaderFlag, 57 kFloat2_GrSLType, "AtlasSizeInv", &atlasDimensionsInvName); 58 59 GrGLSLVarying uv, texIdx; 60 append_index_uv_varyings(args, 61 btgp.numTextureSamplers(), 62 btgp.fInTextureCoords.name(), 63 atlasDimensionsInvName, 64 &uv, 65 &texIdx, 66 nullptr); 67 68 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 69 // Setup pass through color 70 fragBuilder->codeAppendf("half4 %s;", args.fOutputColor); 71 if (btgp.hasVertexColor()) { 72 varyingHandler->addPassThroughAttribute(btgp.fInColor.asShaderVar(), args.fOutputColor); 73 } else { 74 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, 75 &fColorUniform); 76 } 77 78 // Setup position 79 gpArgs->fPositionVar = btgp.fInPosition.asShaderVar(); 80 WriteLocalCoord(vertBuilder, 81 uniformHandler, 82 *args.fShaderCaps, 83 gpArgs, 84 btgp.fInPosition.asShaderVar(), 85 btgp.fLocalMatrix, 86 &fLocalMatrixUniform); 87 88 fragBuilder->codeAppend("half4 texColor;"); 89 append_multitexture_lookup(args, btgp.numTextureSamplers(), 90 texIdx, uv.fsIn(), "texColor"); 91 92 if (btgp.fMaskFormat == kARGB_GrMaskFormat) { 93 // modulate by color 94 fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor); 95 fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage); 96 } else { 97 fragBuilder->codeAppendf("half4 %s = texColor;", args.fOutputCoverage); 98 } 99 } 100 101private: 102 SkPMColor4f fColor = SK_PMColor4fILLEGAL; 103 SkISize fAtlasDimensions = {-1, -1}; 104 SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix(); 105 106 UniformHandle fColorUniform; 107 UniformHandle fAtlasDimensionsInvUniform; 108 UniformHandle fLocalMatrixUniform; 109}; 110 111/////////////////////////////////////////////////////////////////////////////// 112 113GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps, 114 const SkPMColor4f& color, 115 bool wideColor, 116 const GrSurfaceProxyView* views, 117 int numActiveViews, 118 GrSamplerState params, 119 GrMaskFormat format, 120 const SkMatrix& localMatrix, 121 bool usesW) 122 : INHERITED(kGrBitmapTextGeoProc_ClassID) 123 , fColor(color) 124 , fLocalMatrix(localMatrix) 125 , fUsesW(usesW) 126 , fMaskFormat(format) { 127 SkASSERT(numActiveViews <= kMaxTextures); 128 129 if (usesW) { 130 fInPosition = {"inPosition", kFloat3_GrVertexAttribType, kFloat3_GrSLType}; 131 } else { 132 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType}; 133 } 134 135 bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat || 136 kA565_GrMaskFormat == fMaskFormat; 137 if (hasVertexColor) { 138 fInColor = MakeColorAttribute("inColor", wideColor); 139 } 140 141 fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType, 142 caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType}; 143 this->setVertexAttributes(&fInPosition, 3); 144 145 if (numActiveViews) { 146 fAtlasDimensions = views[0].proxy()->dimensions(); 147 } 148 for (int i = 0; i < numActiveViews; ++i) { 149 const GrSurfaceProxy* proxy = views[i].proxy(); 150 SkASSERT(proxy); 151 SkASSERT(proxy->dimensions() == fAtlasDimensions); 152 fTextureSamplers[i].reset(params, proxy->backendFormat(), views[i].swizzle()); 153 } 154 this->setTextureSamplerCnt(numActiveViews); 155} 156 157void GrBitmapTextGeoProc::addNewViews(const GrSurfaceProxyView* views, 158 int numActiveViews, 159 GrSamplerState params) { 160 SkASSERT(numActiveViews <= kMaxTextures); 161 // Just to make sure we don't try to add too many proxies 162 numActiveViews = std::min(numActiveViews, kMaxTextures); 163 164 if (!fTextureSamplers[0].isInitialized()) { 165 fAtlasDimensions = views[0].proxy()->dimensions(); 166 } 167 168 for (int i = 0; i < numActiveViews; ++i) { 169 const GrSurfaceProxy* proxy = views[i].proxy(); 170 SkASSERT(proxy); 171 SkASSERT(proxy->dimensions() == fAtlasDimensions); 172 173 if (!fTextureSamplers[i].isInitialized()) { 174 fTextureSamplers[i].reset(params, proxy->backendFormat(), views[i].swizzle()); 175 } 176 } 177 this->setTextureSamplerCnt(numActiveViews); 178} 179 180SkString GrBitmapTextGeoProc::getShaderDfxInfo() const 181{ 182 SkString format; 183 format.printf("ShaderDfx_GrBitmapTextGeoProc_%d_%d_%d_%d_%d_%d", fUsesW, fMaskFormat, numTextureSamplers(), 184 fLocalMatrix.isIdentity(), fLocalMatrix.isScaleTranslate(), fLocalMatrix.hasPerspective()); 185 return format; 186} 187 188void GrBitmapTextGeoProc::addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { 189 b->addBool(fUsesW, "usesW"); 190 static_assert(kLast_GrMaskFormat < (1u << 2)); 191 b->addBits(2, fMaskFormat, "maskFormat"); 192 b->addBits(ProgramImpl::kMatrixKeyBits, 193 ProgramImpl::ComputeMatrixKey(caps, fLocalMatrix), 194 "localMatrixType"); 195 b->add32(this->numTextureSamplers(), "numTextures"); 196} 197 198std::unique_ptr<GrGeometryProcessor::ProgramImpl> GrBitmapTextGeoProc::makeProgramImpl( 199 const GrShaderCaps& caps) const { 200 return std::make_unique<Impl>(); 201} 202 203/////////////////////////////////////////////////////////////////////////////// 204 205GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc); 206 207#if GR_TEST_UTILS 208 209GrGeometryProcessor* GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) { 210 auto [view, ct, at] = d->randomView(); 211 212 GrSamplerState::WrapMode wrapModes[2]; 213 GrTest::TestWrapModes(d->fRandom, wrapModes); 214 GrSamplerState samplerState(wrapModes, d->fRandom->nextBool() 215 ? GrSamplerState::Filter::kLinear 216 : GrSamplerState::Filter::kNearest); 217 218 GrMaskFormat format; 219 switch (ct) { 220 case GrColorType::kAlpha_8: 221 format = kA8_GrMaskFormat; 222 break; 223 case GrColorType::kBGR_565: 224 format = kA565_GrMaskFormat; 225 break; 226 case GrColorType::kRGBA_8888: 227 default: // It doesn't really matter that color type and mask format agree. 228 format = kARGB_GrMaskFormat; 229 break; 230 } 231 232 GrColor color = GrTest::RandomColor(d->fRandom); 233 bool wideColor = d->fRandom->nextBool(); 234 SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom); 235 bool usesW = d->fRandom->nextBool(); 236 return GrBitmapTextGeoProc::Make(d->allocator(), *d->caps()->shaderCaps(), 237 SkPMColor4f::FromBytes_RGBA(color), 238 wideColor, 239 &view, 1, samplerState, format, 240 localMatrix, usesW); 241} 242#endif 243