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