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