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 "GrAtlasedShaderHelpers.h"
11 #include "GrCaps.h"
12 #include "GrShaderCaps.h"
13 #include "GrTexture.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLGeometryProcessor.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17 #include "glsl/GrGLSLUniformHandler.h"
18 #include "glsl/GrGLSLVarying.h"
19 #include "glsl/GrGLSLVertexGeoBuilder.h"
20
21 class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor {
22 public:
GrGLBitmapTextGeoProc()23 GrGLBitmapTextGeoProc() : fColor(SK_PMColor4fILLEGAL), fAtlasSize({0,0}) {}
24
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)25 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
26 const GrBitmapTextGeoProc& btgp = args.fGP.cast<GrBitmapTextGeoProc>();
27
28 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
29 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
30 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
31
32 // emit attributes
33 varyingHandler->emitAttributes(btgp);
34
35 const char* atlasSizeInvName;
36 fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
37 kFloat2_GrSLType,
38 kHigh_GrSLPrecision,
39 "AtlasSizeInv",
40 &atlasSizeInvName);
41
42 GrGLSLVarying uv(kFloat2_GrSLType);
43 GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
44 GrGLSLVarying texIdx(texIdxType);
45 append_index_uv_varyings(args, btgp.inTextureCoords().name(), atlasSizeInvName, &uv,
46 &texIdx, nullptr);
47
48 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
49 // Setup pass through color
50 if (btgp.hasVertexColor()) {
51 varyingHandler->addPassThroughAttribute(btgp.inColor(), args.fOutputColor);
52 } else {
53 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
54 &fColorUniform);
55 }
56
57 // Setup position
58 gpArgs->fPositionVar = btgp.inPosition().asShaderVar();
59
60 // emit transforms
61 this->emitTransforms(vertBuilder,
62 varyingHandler,
63 uniformHandler,
64 btgp.inPosition().asShaderVar(),
65 btgp.localMatrix(),
66 args.fFPCoordTransformHandler);
67
68 fragBuilder->codeAppend("half4 texColor;");
69 append_multitexture_lookup(args, btgp.numTextureSamplers(),
70 texIdx, uv.fsIn(), "texColor");
71
72 if (btgp.maskFormat() == kARGB_GrMaskFormat) {
73 // modulate by color
74 fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
75 fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
76 } else {
77 fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
78 }
79 }
80
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & gp,FPCoordTransformIter && transformIter)81 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
82 FPCoordTransformIter&& transformIter) override {
83 const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
84 if (btgp.color() != fColor && !btgp.hasVertexColor()) {
85 pdman.set4fv(fColorUniform, 1, btgp.color().vec());
86 fColor = btgp.color();
87 }
88
89 const SkISize& atlasSize = btgp.atlasSize();
90 SkASSERT(SkIsPow2(atlasSize.fWidth) && SkIsPow2(atlasSize.fHeight));
91
92 if (fAtlasSize != atlasSize) {
93 pdman.set2f(fAtlasSizeInvUniform, 1.0f / atlasSize.fWidth, 1.0f / atlasSize.fHeight);
94 fAtlasSize = atlasSize;
95 }
96 this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
97 }
98
GenKey(const GrGeometryProcessor & proc,const GrShaderCaps &,GrProcessorKeyBuilder * b)99 static inline void GenKey(const GrGeometryProcessor& proc,
100 const GrShaderCaps&,
101 GrProcessorKeyBuilder* b) {
102 const GrBitmapTextGeoProc& btgp = proc.cast<GrBitmapTextGeoProc>();
103 uint32_t key = 0;
104 key |= btgp.usesW() ? 0x1 : 0x0;
105 key |= btgp.maskFormat() << 1;
106 b->add32(key);
107 b->add32(btgp.numTextureSamplers());
108 }
109
110 private:
111 SkPMColor4f fColor;
112 UniformHandle fColorUniform;
113
114 SkISize fAtlasSize;
115 UniformHandle fAtlasSizeInvUniform;
116
117 typedef GrGLSLGeometryProcessor INHERITED;
118 };
119
120 ///////////////////////////////////////////////////////////////////////////////
121
GrBitmapTextGeoProc(const GrShaderCaps & caps,const SkPMColor4f & color,bool wideColor,const sk_sp<GrTextureProxy> * proxies,int numActiveProxies,const GrSamplerState & params,GrMaskFormat format,const SkMatrix & localMatrix,bool usesW)122 GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps,
123 const SkPMColor4f& color,
124 bool wideColor,
125 const sk_sp<GrTextureProxy>* proxies,
126 int numActiveProxies,
127 const GrSamplerState& params, GrMaskFormat format,
128 const SkMatrix& localMatrix, bool usesW)
129 : INHERITED(kGrBitmapTextGeoProc_ClassID)
130 , fColor(color)
131 , fLocalMatrix(localMatrix)
132 , fUsesW(usesW)
133 , fMaskFormat(format) {
134 SkASSERT(numActiveProxies <= kMaxTextures);
135
136 if (usesW) {
137 fInPosition = {"inPosition", kFloat3_GrVertexAttribType, kFloat3_GrSLType};
138 } else {
139 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
140 }
141
142 bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
143 kA565_GrMaskFormat == fMaskFormat;
144 if (hasVertexColor) {
145 fInColor = MakeColorAttribute("inColor", wideColor);
146 }
147
148 fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
149 caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
150 this->setVertexAttributes(&fInPosition, 3);
151
152 if (numActiveProxies) {
153 fAtlasSize = proxies[0]->isize();
154 }
155 for (int i = 0; i < numActiveProxies; ++i) {
156 SkASSERT(proxies[i]);
157 SkASSERT(proxies[i]->isize() == fAtlasSize);
158 fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
159 }
160 this->setTextureSamplerCnt(numActiveProxies);
161 }
162
addNewProxies(const sk_sp<GrTextureProxy> * proxies,int numActiveProxies,const GrSamplerState & params)163 void GrBitmapTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
164 int numActiveProxies,
165 const GrSamplerState& params) {
166 SkASSERT(numActiveProxies <= kMaxTextures);
167
168 if (!fTextureSamplers[0].isInitialized()) {
169 fAtlasSize = proxies[0]->isize();
170 }
171
172 for (int i = 0; i < numActiveProxies; ++i) {
173 SkASSERT(proxies[i]);
174 SkASSERT(proxies[i]->isize() == fAtlasSize);
175
176 if (!fTextureSamplers[i].isInitialized()) {
177 fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params);
178 }
179 }
180 this->setTextureSamplerCnt(numActiveProxies);
181 }
182
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const183 void GrBitmapTextGeoProc::getGLSLProcessorKey(const GrShaderCaps& caps,
184 GrProcessorKeyBuilder* b) const {
185 GrGLBitmapTextGeoProc::GenKey(*this, caps, b);
186 }
187
createGLSLInstance(const GrShaderCaps & caps) const188 GrGLSLPrimitiveProcessor* GrBitmapTextGeoProc::createGLSLInstance(const GrShaderCaps& caps) const {
189 return new GrGLBitmapTextGeoProc();
190 }
191
192 ///////////////////////////////////////////////////////////////////////////////
193
194 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
195
196 #if GR_TEST_UTILS
197
TestCreate(GrProcessorTestData * d)198 sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
199 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
200 : GrProcessorUnitTest::kAlphaTextureIdx;
201 sk_sp<GrTextureProxy> proxies[kMaxTextures] = {
202 d->textureProxy(texIdx),
203 nullptr,
204 nullptr,
205 nullptr
206 };
207
208 GrSamplerState::WrapMode wrapModes[2];
209 GrTest::TestWrapModes(d->fRandom, wrapModes);
210 GrSamplerState samplerState(wrapModes, d->fRandom->nextBool()
211 ? GrSamplerState::Filter::kBilerp
212 : GrSamplerState::Filter::kNearest);
213
214 GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning
215 switch (d->fRandom->nextULessThan(3)) {
216 case 0:
217 format = kA8_GrMaskFormat;
218 break;
219 case 1:
220 format = kA565_GrMaskFormat;
221 break;
222 case 2:
223 format = kARGB_GrMaskFormat;
224 break;
225 }
226
227 return GrBitmapTextGeoProc::Make(*d->caps()->shaderCaps(),
228 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
229 d->fRandom->nextBool(),
230 proxies, 1, samplerState, format,
231 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
232 }
233 #endif
234