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