2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/gpu/ganesh/effects/GrBitmapTextGeoProc.h"
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/GrGLSLFragmentShaderBuilder.h"
16 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
17 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
18 #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
19 #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
21 using MaskFormat = skgpu::MaskFormat;
23 class GrBitmapTextGeoProc::Impl : public ProgramImpl {
25 void setData(const GrGLSLProgramDataManager& pdman,
26 const GrShaderCaps& shaderCaps,
27 const GrGeometryProcessor& geomProc) override {
28 const GrBitmapTextGeoProc& btgp = geomProc.cast<GrBitmapTextGeoProc>();
29 if (btgp.fColor != fColor && !btgp.hasVertexColor()) {
30 pdman.set4fv(fColorUniform, 1, btgp.fColor.vec());
34 const SkISize& atlasDimensions = btgp.fAtlasDimensions;
35 SkASSERT(SkIsPow2(atlasDimensions.fWidth) && SkIsPow2(atlasDimensions.fHeight));
37 if (fAtlasDimensions != atlasDimensions) {
38 pdman.set2f(fAtlasDimensionsInvUniform,
39 1.0f / atlasDimensions.fWidth,
40 1.0f / atlasDimensions.fHeight);
41 fAtlasDimensions = atlasDimensions;
44 SetTransform(pdman, shaderCaps, fLocalMatrixUniform, btgp.fLocalMatrix, &fLocalMatrix);
48 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
49 const GrBitmapTextGeoProc& btgp = args.fGeomProc.cast<GrBitmapTextGeoProc>();
51 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
52 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
53 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
56 varyingHandler->emitAttributes(btgp);
58 const char* atlasDimensionsInvName;
59 fAtlasDimensionsInvUniform = uniformHandler->addUniform(nullptr, kVertex_GrShaderFlag,
60 SkSLType::kFloat2, "AtlasSizeInv", &atlasDimensionsInvName);
62 GrGLSLVarying uv, texIdx;
63 append_index_uv_varyings(args,
64 btgp.numTextureSamplers(),
65 btgp.fInTextureCoords.name(),
66 atlasDimensionsInvName,
71 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
72 // Setup pass through color
73 fragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
74 if (btgp.hasVertexColor()) {
75 varyingHandler->addPassThroughAttribute(btgp.fInColor.asShaderVar(), args.fOutputColor);
77 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
82 gpArgs->fPositionVar = btgp.fInPosition.asShaderVar();
83 WriteLocalCoord(vertBuilder,
87 btgp.fInPosition.asShaderVar(),
89 &fLocalMatrixUniform);
91 fragBuilder->codeAppend("half4 texColor;");
92 append_multitexture_lookup(args, btgp.numTextureSamplers(),
93 texIdx, uv.fsIn(), "texColor");
95 if (btgp.fMaskFormat == MaskFormat::kARGB) {
97 fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
98 fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
100 fragBuilder->codeAppendf("half4 %s = texColor;", args.fOutputCoverage);
105 SkPMColor4f fColor = SK_PMColor4fILLEGAL;
106 SkISize fAtlasDimensions = {-1, -1};
107 SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
109 UniformHandle fColorUniform;
110 UniformHandle fAtlasDimensionsInvUniform;
111 UniformHandle fLocalMatrixUniform;
114 ///////////////////////////////////////////////////////////////////////////////
116 GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps,
117 const SkPMColor4f& color,
119 const GrSurfaceProxyView* views,
121 GrSamplerState params,
123 const SkMatrix& localMatrix,
125 : INHERITED(kGrBitmapTextGeoProc_ClassID)
127 , fLocalMatrix(localMatrix)
129 , fMaskFormat(format) {
130 SkASSERT(numActiveViews <= kMaxTextures);
133 fInPosition = {"inPosition", kFloat3_GrVertexAttribType, SkSLType::kFloat3};
135 fInPosition = {"inPosition", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
138 bool hasVertexColor = MaskFormat::kA8 == fMaskFormat || MaskFormat::kA565 == fMaskFormat;
139 if (hasVertexColor) {
140 fInColor = MakeColorAttribute("inColor", wideColor);
143 fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
144 caps.integerSupport() ? SkSLType::kUShort2 : SkSLType::kFloat2};
145 this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
147 if (numActiveViews) {
148 fAtlasDimensions = views[0].proxy()->dimensions();
150 for (int i = 0; i < numActiveViews; ++i) {
151 const GrSurfaceProxy* proxy = views[i].proxy();
153 SkASSERT(proxy->dimensions() == fAtlasDimensions);
154 fTextureSamplers[i].reset(params, proxy->backendFormat(), views[i].swizzle());
156 this->setTextureSamplerCnt(numActiveViews);
159 void GrBitmapTextGeoProc::addNewViews(const GrSurfaceProxyView* views,
161 GrSamplerState params) {
162 SkASSERT(numActiveViews <= kMaxTextures);
163 // Just to make sure we don't try to add too many proxies
164 numActiveViews = std::min(numActiveViews, kMaxTextures);
166 if (!fTextureSamplers[0].isInitialized()) {
167 fAtlasDimensions = views[0].proxy()->dimensions();
170 for (int i = 0; i < numActiveViews; ++i) {
171 const GrSurfaceProxy* proxy = views[i].proxy();
173 SkASSERT(proxy->dimensions() == fAtlasDimensions);
175 if (!fTextureSamplers[i].isInitialized()) {
176 fTextureSamplers[i].reset(params, proxy->backendFormat(), views[i].swizzle());
179 this->setTextureSamplerCnt(numActiveViews);
182 void GrBitmapTextGeoProc::addToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
183 b->addBool(fUsesW, "usesW");
184 static_assert(static_cast<int>(MaskFormat::kLast) < (1u << 2));
185 b->addBits(2, static_cast<int>(fMaskFormat), "maskFormat");
186 b->addBits(ProgramImpl::kMatrixKeyBits,
187 ProgramImpl::ComputeMatrixKey(caps, fLocalMatrix),
189 b->add32(this->numTextureSamplers(), "numTextures");
192 std::unique_ptr<GrGeometryProcessor::ProgramImpl> GrBitmapTextGeoProc::makeProgramImpl(
193 const GrShaderCaps& caps) const {
194 return std::make_unique<Impl>();
197 ///////////////////////////////////////////////////////////////////////////////
199 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
203 GrGeometryProcessor* GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
204 auto [view, ct, at] = d->randomView();
206 GrSamplerState::WrapMode wrapModes[2];
207 GrTest::TestWrapModes(d->fRandom, wrapModes);
208 GrSamplerState samplerState(wrapModes, d->fRandom->nextBool()
209 ? GrSamplerState::Filter::kLinear
210 : GrSamplerState::Filter::kNearest);
214 case GrColorType::kAlpha_8:
215 format = MaskFormat::kA8;
217 case GrColorType::kBGR_565:
218 format = MaskFormat::kA565;
220 case GrColorType::kRGBA_8888:
221 default: // It doesn't really matter that color type and mask format agree.
222 format = MaskFormat::kARGB;
226 GrColor color = GrTest::RandomColor(d->fRandom);
227 bool wideColor = d->fRandom->nextBool();
228 SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
229 bool usesW = d->fRandom->nextBool();
230 return GrBitmapTextGeoProc::Make(d->allocator(), *d->caps()->shaderCaps(),
231 SkPMColor4f::FromBytes_RGBA(color),
233 &view, 1, samplerState, format,