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:
GrGLBitmapTextGeoProc()20     GrGLBitmapTextGeoProc() : fColor(GrColor_ILLEGAL) {}
21 
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)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 
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & gp,FPCoordTransformIter && transformIter)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 
GenKey(const GrGeometryProcessor & proc,const GrShaderCaps &,GrProcessorKeyBuilder * b)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 
GrBitmapTextGeoProc(GrResourceProvider * resourceProvider,GrColor color,sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params,GrMaskFormat format,const SkMatrix & localMatrix,bool usesLocalCoords)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 
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const145 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
146                                               GrProcessorKeyBuilder* b) const {
147     GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
148 }
149 
createGLSLInstance(const GrShaderCaps & caps) const150 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
TestCreate(GrProcessorTestData * d)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