• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC.
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/ops/AtlasInstancedHelper.h"
9 
10 #include "src/gpu/BufferWriter.h"
11 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "src/gpu/glsl/GrGLSLVarying.h"
13 #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
14 
15 namespace skgpu::v1 {
16 
appendInstanceAttribs(SkTArray<GrGeometryProcessor::Attribute> * instanceAttribs) const17 void AtlasInstancedHelper::appendInstanceAttribs(
18         SkTArray<GrGeometryProcessor::Attribute>* instanceAttribs) const {
19     instanceAttribs->emplace_back("locations", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
20     if (fShaderFlags & ShaderFlags::kCheckBounds) {
21         instanceAttribs->emplace_back("sizeInAtlas", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
22     }
23 }
24 
writeInstanceData(VertexWriter * instanceWriter,const Instance * i) const25 void AtlasInstancedHelper::writeInstanceData(VertexWriter* instanceWriter,
26                                              const Instance* i) const {
27     SkASSERT(i->fLocationInAtlas.x() >= 0);
28     SkASSERT(i->fLocationInAtlas.y() >= 0);
29     *instanceWriter <<
30             // A negative x coordinate in the atlas indicates that the path is transposed.
31             // Also add 1 since we can't negate zero.
32             ((float)(i->fTransposedInAtlas ? -i->fLocationInAtlas.x() - 1
33                      : i->fLocationInAtlas.x() + 1)) <<
34             (float)i->fLocationInAtlas.y() <<
35             (float)i->fPathDevIBounds.left() <<
36             (float)i->fPathDevIBounds.top() <<
37             VertexWriter::If(fShaderFlags & ShaderFlags::kCheckBounds,
38                              SkSize::Make(i->fPathDevIBounds.size()));
39 }
40 
injectShaderCode(const GrGeometryProcessor::ProgramImpl::EmitArgs & args,const GrShaderVar & devCoord,GrGLSLUniformHandler::UniformHandle * atlasAdjustUniformHandle) const41 void AtlasInstancedHelper::injectShaderCode(
42         const GrGeometryProcessor::ProgramImpl::EmitArgs& args,
43         const GrShaderVar& devCoord,
44         GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const {
45     GrGLSLVarying atlasCoord(kFloat2_GrSLType);
46     args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord);
47 
48     const char* atlasAdjustName;
49     *atlasAdjustUniformHandle = args.fUniformHandler->addUniform(
50             nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjustName);
51 
52     args.fVertBuilder->codeAppendf(R"(
53     // A negative x coordinate in the atlas indicates that the path is transposed.
54     // We also added 1 since we can't negate zero.
55     float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y);
56     float2 devTopLeft = locations.zw;
57     bool transposed = locations.x < 0;
58     float2 atlasCoord = %s - devTopLeft;
59     if (transposed) {
60         atlasCoord = atlasCoord.yx;
61     }
62     atlasCoord += atlasTopLeft;
63     %s = atlasCoord * %s;)", devCoord.c_str(), atlasCoord.vsOut(), atlasAdjustName);
64 
65     if (fShaderFlags & ShaderFlags::kCheckBounds) {
66         GrGLSLVarying atlasBounds(kFloat4_GrSLType);
67         args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds,
68                                          GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
69         args.fVertBuilder->codeAppendf(R"(
70         float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx
71                                                              : sizeInAtlas.00xy);
72         %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjustName);
73 
74         args.fFragBuilder->codeAppendf(R"(
75         half atlasCoverage = 0;
76         float2 atlasCoord = %s;
77         float4 atlasBounds = %s;
78         if (all(greaterThan(atlasCoord, atlasBounds.xy)) &&
79             all(lessThan(atlasCoord, atlasBounds.zw))) {
80             atlasCoverage = )", atlasCoord.fsIn(), atlasBounds.fsIn());
81         args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord");
82         args.fFragBuilder->codeAppendf(R"(.a;
83         })");
84     } else {
85         args.fFragBuilder->codeAppendf("half atlasCoverage = ");
86         args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
87         args.fFragBuilder->codeAppendf(".a;");
88     }
89 
90     if (fShaderFlags & ShaderFlags::kInvertCoverage) {
91         args.fFragBuilder->codeAppendf("%s *= (1 - atlasCoverage);", args.fOutputCoverage);
92     } else {
93         args.fFragBuilder->codeAppendf("%s *= atlasCoverage;", args.fOutputCoverage);
94     }
95 }
96 
setUniformData(const GrGLSLProgramDataManager & pdman,const GrGLSLUniformHandler::UniformHandle & atlasAdjustUniformHandle) const97 void AtlasInstancedHelper::setUniformData(
98         const GrGLSLProgramDataManager& pdman,
99         const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const {
100     SkASSERT(fAtlasProxy->isInstantiated());
101     SkISize dimensions = fAtlasProxy->backingStoreDimensions();
102     pdman.set2f(atlasAdjustUniformHandle, 1.f / dimensions.width(), 1.f / dimensions.height());
103 }
104 
105 } // namespace skgpu::v1
106