1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2020 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/AtlasInstancedHelper.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/KeyBuilder.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::ganesh {
23*c8dee2aaSAndroid Build Coastguard Worker
getKeyBits(KeyBuilder * b) const24*c8dee2aaSAndroid Build Coastguard Worker void AtlasInstancedHelper::getKeyBits(KeyBuilder* b) const {
25*c8dee2aaSAndroid Build Coastguard Worker b->addBits(kNumShaderFlags, (int)fShaderFlags, "atlasFlags");
26*c8dee2aaSAndroid Build Coastguard Worker }
27*c8dee2aaSAndroid Build Coastguard Worker
appendInstanceAttribs(TArray<GrGeometryProcessor::Attribute> * instanceAttribs) const28*c8dee2aaSAndroid Build Coastguard Worker void AtlasInstancedHelper::appendInstanceAttribs(
29*c8dee2aaSAndroid Build Coastguard Worker TArray<GrGeometryProcessor::Attribute>* instanceAttribs) const {
30*c8dee2aaSAndroid Build Coastguard Worker instanceAttribs->emplace_back("locations", kFloat4_GrVertexAttribType, SkSLType::kFloat4);
31*c8dee2aaSAndroid Build Coastguard Worker if (fShaderFlags & ShaderFlags::kCheckBounds) {
32*c8dee2aaSAndroid Build Coastguard Worker instanceAttribs->emplace_back("sizeInAtlas", kFloat2_GrVertexAttribType, SkSLType::kFloat2);
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker }
35*c8dee2aaSAndroid Build Coastguard Worker
writeInstanceData(VertexWriter * instanceWriter,const Instance * i) const36*c8dee2aaSAndroid Build Coastguard Worker void AtlasInstancedHelper::writeInstanceData(VertexWriter* instanceWriter,
37*c8dee2aaSAndroid Build Coastguard Worker const Instance* i) const {
38*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i->fLocationInAtlas.x() >= 0);
39*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i->fLocationInAtlas.y() >= 0);
40*c8dee2aaSAndroid Build Coastguard Worker *instanceWriter <<
41*c8dee2aaSAndroid Build Coastguard Worker // A negative x coordinate in the atlas indicates that the path is transposed.
42*c8dee2aaSAndroid Build Coastguard Worker // Also add 1 since we can't negate zero.
43*c8dee2aaSAndroid Build Coastguard Worker ((float)(i->fTransposedInAtlas ? -i->fLocationInAtlas.x() - 1
44*c8dee2aaSAndroid Build Coastguard Worker : i->fLocationInAtlas.x() + 1)) <<
45*c8dee2aaSAndroid Build Coastguard Worker (float)i->fLocationInAtlas.y() <<
46*c8dee2aaSAndroid Build Coastguard Worker (float)i->fPathDevIBounds.left() <<
47*c8dee2aaSAndroid Build Coastguard Worker (float)i->fPathDevIBounds.top() <<
48*c8dee2aaSAndroid Build Coastguard Worker VertexWriter::If(fShaderFlags & ShaderFlags::kCheckBounds,
49*c8dee2aaSAndroid Build Coastguard Worker SkSize::Make(i->fPathDevIBounds.size()));
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
injectShaderCode(const GrGeometryProcessor::ProgramImpl::EmitArgs & args,const GrShaderVar & devCoord,GrGLSLUniformHandler::UniformHandle * atlasAdjustUniformHandle) const52*c8dee2aaSAndroid Build Coastguard Worker void AtlasInstancedHelper::injectShaderCode(
53*c8dee2aaSAndroid Build Coastguard Worker const GrGeometryProcessor::ProgramImpl::EmitArgs& args,
54*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar& devCoord,
55*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const {
56*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVarying atlasCoord(SkSLType::kFloat2);
57*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord);
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker const char* atlasAdjustName;
60*c8dee2aaSAndroid Build Coastguard Worker *atlasAdjustUniformHandle = args.fUniformHandler->addUniform(
61*c8dee2aaSAndroid Build Coastguard Worker nullptr, kVertex_GrShaderFlag, SkSLType::kFloat2, "atlas_adjust", &atlasAdjustName);
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker args.fVertBuilder->codeAppendf(
64*c8dee2aaSAndroid Build Coastguard Worker // A negative x coordinate in the atlas indicates that the path is transposed.
65*c8dee2aaSAndroid Build Coastguard Worker // We also added 1 since we can't negate zero.
66*c8dee2aaSAndroid Build Coastguard Worker "float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y);"
67*c8dee2aaSAndroid Build Coastguard Worker "float2 devTopLeft = locations.zw;"
68*c8dee2aaSAndroid Build Coastguard Worker "bool transposed = locations.x < 0;"
69*c8dee2aaSAndroid Build Coastguard Worker "float2 atlasCoord = %s - devTopLeft;"
70*c8dee2aaSAndroid Build Coastguard Worker "if (transposed) {"
71*c8dee2aaSAndroid Build Coastguard Worker "atlasCoord = atlasCoord.yx;"
72*c8dee2aaSAndroid Build Coastguard Worker "}"
73*c8dee2aaSAndroid Build Coastguard Worker "atlasCoord += atlasTopLeft;"
74*c8dee2aaSAndroid Build Coastguard Worker "%s = atlasCoord * %s;", devCoord.c_str(), atlasCoord.vsOut(), atlasAdjustName);
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker if (fShaderFlags & ShaderFlags::kCheckBounds) {
77*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVarying atlasBounds(SkSLType::kFloat4);
78*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds,
79*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
80*c8dee2aaSAndroid Build Coastguard Worker args.fVertBuilder->codeAppendf(R"(
81*c8dee2aaSAndroid Build Coastguard Worker float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx
82*c8dee2aaSAndroid Build Coastguard Worker : sizeInAtlas.00xy);
83*c8dee2aaSAndroid Build Coastguard Worker %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjustName);
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf(
86*c8dee2aaSAndroid Build Coastguard Worker "half atlasCoverage = 0;"
87*c8dee2aaSAndroid Build Coastguard Worker "float2 atlasCoord = %s;"
88*c8dee2aaSAndroid Build Coastguard Worker "float4 atlasBounds = %s;"
89*c8dee2aaSAndroid Build Coastguard Worker "if (all(greaterThan(atlasCoord, atlasBounds.xy)) &&"
90*c8dee2aaSAndroid Build Coastguard Worker "all(lessThan(atlasCoord, atlasBounds.zw))) {"
91*c8dee2aaSAndroid Build Coastguard Worker "atlasCoverage = ", atlasCoord.fsIn(), atlasBounds.fsIn());
92*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord");
93*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf(R"(.a;
94*c8dee2aaSAndroid Build Coastguard Worker })");
95*c8dee2aaSAndroid Build Coastguard Worker } else {
96*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf("half atlasCoverage = ");
97*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
98*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf(".a;");
99*c8dee2aaSAndroid Build Coastguard Worker }
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker if (fShaderFlags & ShaderFlags::kInvertCoverage) {
102*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf("%s *= (1 - atlasCoverage);", args.fOutputCoverage);
103*c8dee2aaSAndroid Build Coastguard Worker } else {
104*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf("%s *= atlasCoverage;", args.fOutputCoverage);
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker
setUniformData(const GrGLSLProgramDataManager & pdman,const GrGLSLUniformHandler::UniformHandle & atlasAdjustUniformHandle) const108*c8dee2aaSAndroid Build Coastguard Worker void AtlasInstancedHelper::setUniformData(
109*c8dee2aaSAndroid Build Coastguard Worker const GrGLSLProgramDataManager& pdman,
110*c8dee2aaSAndroid Build Coastguard Worker const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const {
111*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fAtlasProxy->isInstantiated());
112*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions = fAtlasProxy->backingStoreDimensions();
113*c8dee2aaSAndroid Build Coastguard Worker pdman.set2f(atlasAdjustUniformHandle, 1.f / dimensions.width(), 1.f / dimensions.height());
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::ganesh
117