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