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