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