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