blob: 1a75a016efb0e8ecb4cc183e6dda034d86038884 [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(
Brian Salomonf95940b2021-08-09 15:56:24 -040040 const GrGeometryProcessor::ProgramImpl::EmitArgs& args,
41 const GrShaderVar& devCoord,
Chris Daltonb1fd64e2021-07-08 15:38:51 -060042 GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const {
43 GrGLSLVarying atlasCoord(kFloat2_GrSLType);
44 args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord);
45
46 const char* atlasAdjustName;
47 *atlasAdjustUniformHandle = args.fUniformHandler->addUniform(
48 nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjustName);
49
50 args.fVertBuilder->codeAppendf(R"(
51 // A negative x coordinate in the atlas indicates that the path is transposed.
52 // We also added 1 since we can't negate zero.
53 float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y);
54 float2 devTopLeft = locations.zw;
55 bool transposed = locations.x < 0;
56 float2 atlasCoord = %s - devTopLeft;
57 if (transposed) {
58 atlasCoord = atlasCoord.yx;
59 }
60 atlasCoord += atlasTopLeft;
61 %s = atlasCoord * %s;)", devCoord.c_str(), atlasCoord.vsOut(), atlasAdjustName);
62
63 if (fShaderFlags & ShaderFlags::kCheckBounds) {
64 GrGLSLVarying atlasBounds(kFloat4_GrSLType);
65 args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds,
66 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
67 args.fVertBuilder->codeAppendf(R"(
68 float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx
69 : sizeInAtlas.00xy);
70 %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjustName);
71
72 args.fFragBuilder->codeAppendf(R"(
73 half atlasCoverage = 0;
74 float2 atlasCoord = %s;
75 float4 atlasBounds = %s;
76 if (all(greaterThan(atlasCoord, atlasBounds.xy)) &&
77 all(lessThan(atlasCoord, atlasBounds.zw))) {
78 atlasCoverage = )", atlasCoord.fsIn(), atlasBounds.fsIn());
79 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord");
80 args.fFragBuilder->codeAppendf(R"(.a;
81 })");
82 } else {
83 args.fFragBuilder->codeAppendf("half atlasCoverage = ");
84 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
85 args.fFragBuilder->codeAppendf(".a;");
86 }
87
88 if (fShaderFlags & ShaderFlags::kInvertCoverage) {
89 args.fFragBuilder->codeAppendf("%s *= (1 - atlasCoverage);", args.fOutputCoverage);
90 } else {
91 args.fFragBuilder->codeAppendf("%s *= atlasCoverage;", args.fOutputCoverage);
92 }
93}
94
95void GrAtlasInstancedHelper::setUniformData(
96 const GrGLSLProgramDataManager& pdman,
97 const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const {
98 SkASSERT(fAtlasProxy->isInstantiated());
99 SkISize dimensions = fAtlasProxy->backingStoreDimensions();
100 pdman.set2f(atlasAdjustUniformHandle, 1.f / dimensions.width(), 1.f / dimensions.height());
101}