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