blob: f5914a0382bb760fa628ad227e56c93079743a4d [file] [log] [blame]
Chris Daltonb1fd64e2021-07-08 15:38:51 -06001/*
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
Robert Phillipsef80d7b2021-09-14 16:10:56 -04008#include "src/gpu/ops/AtlasInstancedHelper.h"
Chris Daltonb1fd64e2021-07-08 15:38:51 -06009
10#include "src/gpu/GrVertexWriter.h"
11#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
12#include "src/gpu/glsl/GrGLSLVarying.h"
13#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
14
Robert Phillipsef80d7b2021-09-14 16:10:56 -040015namespace skgpu::v1 {
16
17void AtlasInstancedHelper::appendInstanceAttribs(
Chris Daltonb1fd64e2021-07-08 15:38:51 -060018 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
Robert Phillipsef80d7b2021-09-14 16:10:56 -040025void AtlasInstancedHelper::writeInstanceData(GrVertexWriter* instanceWriter,
26 const Instance* i) const {
Chris Daltonb1fd64e2021-07-08 15:38:51 -060027 SkASSERT(i->fLocationInAtlas.x() >= 0);
28 SkASSERT(i->fLocationInAtlas.y() >= 0);
29 instanceWriter->write(
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 GrVertexWriter::If(fShaderFlags & ShaderFlags::kCheckBounds,
38 SkSize::Make(i->fPathDevIBounds.size())));
39}
40
Robert Phillipsef80d7b2021-09-14 16:10:56 -040041void AtlasInstancedHelper::injectShaderCode(
Brian Salomonf95940b2021-08-09 15:56:24 -040042 const GrGeometryProcessor::ProgramImpl::EmitArgs& args,
43 const GrShaderVar& devCoord,
Chris Daltonb1fd64e2021-07-08 15:38:51 -060044 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
Robert Phillipsef80d7b2021-09-14 16:10:56 -040097void AtlasInstancedHelper::setUniformData(
Chris Daltonb1fd64e2021-07-08 15:38:51 -060098 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}
Robert Phillipsef80d7b2021-09-14 16:10:56 -0400104
105} // namespace skgpu::v1