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