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