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