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 15namespace skgpu::v1 { 16 17void 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 25void 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 41void 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 97void 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