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