1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/ops/AtlasInstancedHelper.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h" 11cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 12cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 13cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cinamespace skgpu::v1 { 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_civoid AtlasInstancedHelper::appendInstanceAttribs( 18cb93a386Sopenharmony_ci SkTArray<GrGeometryProcessor::Attribute>* instanceAttribs) const { 19cb93a386Sopenharmony_ci instanceAttribs->emplace_back("locations", kFloat4_GrVertexAttribType, kFloat4_GrSLType); 20cb93a386Sopenharmony_ci if (fShaderFlags & ShaderFlags::kCheckBounds) { 21cb93a386Sopenharmony_ci instanceAttribs->emplace_back("sizeInAtlas", kFloat2_GrVertexAttribType, kFloat2_GrSLType); 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci} 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_civoid AtlasInstancedHelper::writeInstanceData(VertexWriter* instanceWriter, 26cb93a386Sopenharmony_ci const Instance* i) const { 27cb93a386Sopenharmony_ci SkASSERT(i->fLocationInAtlas.x() >= 0); 28cb93a386Sopenharmony_ci SkASSERT(i->fLocationInAtlas.y() >= 0); 29cb93a386Sopenharmony_ci *instanceWriter << 30cb93a386Sopenharmony_ci // A negative x coordinate in the atlas indicates that the path is transposed. 31cb93a386Sopenharmony_ci // Also add 1 since we can't negate zero. 32cb93a386Sopenharmony_ci ((float)(i->fTransposedInAtlas ? -i->fLocationInAtlas.x() - 1 33cb93a386Sopenharmony_ci : i->fLocationInAtlas.x() + 1)) << 34cb93a386Sopenharmony_ci (float)i->fLocationInAtlas.y() << 35cb93a386Sopenharmony_ci (float)i->fPathDevIBounds.left() << 36cb93a386Sopenharmony_ci (float)i->fPathDevIBounds.top() << 37cb93a386Sopenharmony_ci VertexWriter::If(fShaderFlags & ShaderFlags::kCheckBounds, 38cb93a386Sopenharmony_ci SkSize::Make(i->fPathDevIBounds.size())); 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_civoid AtlasInstancedHelper::injectShaderCode( 42cb93a386Sopenharmony_ci const GrGeometryProcessor::ProgramImpl::EmitArgs& args, 43cb93a386Sopenharmony_ci const GrShaderVar& devCoord, 44cb93a386Sopenharmony_ci GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const { 45cb93a386Sopenharmony_ci GrGLSLVarying atlasCoord(kFloat2_GrSLType); 46cb93a386Sopenharmony_ci args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord); 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci const char* atlasAdjustName; 49cb93a386Sopenharmony_ci *atlasAdjustUniformHandle = args.fUniformHandler->addUniform( 50cb93a386Sopenharmony_ci nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjustName); 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"( 53cb93a386Sopenharmony_ci // A negative x coordinate in the atlas indicates that the path is transposed. 54cb93a386Sopenharmony_ci // We also added 1 since we can't negate zero. 55cb93a386Sopenharmony_ci float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y); 56cb93a386Sopenharmony_ci float2 devTopLeft = locations.zw; 57cb93a386Sopenharmony_ci bool transposed = locations.x < 0; 58cb93a386Sopenharmony_ci float2 atlasCoord = %s - devTopLeft; 59cb93a386Sopenharmony_ci if (transposed) { 60cb93a386Sopenharmony_ci atlasCoord = atlasCoord.yx; 61cb93a386Sopenharmony_ci } 62cb93a386Sopenharmony_ci atlasCoord += atlasTopLeft; 63cb93a386Sopenharmony_ci %s = atlasCoord * %s;)", devCoord.c_str(), atlasCoord.vsOut(), atlasAdjustName); 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci if (fShaderFlags & ShaderFlags::kCheckBounds) { 66cb93a386Sopenharmony_ci GrGLSLVarying atlasBounds(kFloat4_GrSLType); 67cb93a386Sopenharmony_ci args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds, 68cb93a386Sopenharmony_ci GrGLSLVaryingHandler::Interpolation::kCanBeFlat); 69cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"( 70cb93a386Sopenharmony_ci float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx 71cb93a386Sopenharmony_ci : sizeInAtlas.00xy); 72cb93a386Sopenharmony_ci %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjustName); 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf(R"( 75cb93a386Sopenharmony_ci half atlasCoverage = 0; 76cb93a386Sopenharmony_ci float2 atlasCoord = %s; 77cb93a386Sopenharmony_ci float4 atlasBounds = %s; 78cb93a386Sopenharmony_ci if (all(greaterThan(atlasCoord, atlasBounds.xy)) && 79cb93a386Sopenharmony_ci all(lessThan(atlasCoord, atlasBounds.zw))) { 80cb93a386Sopenharmony_ci atlasCoverage = )", atlasCoord.fsIn(), atlasBounds.fsIn()); 81cb93a386Sopenharmony_ci args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord"); 82cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf(R"(.a; 83cb93a386Sopenharmony_ci })"); 84cb93a386Sopenharmony_ci } else { 85cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("half atlasCoverage = "); 86cb93a386Sopenharmony_ci args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn()); 87cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf(".a;"); 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci if (fShaderFlags & ShaderFlags::kInvertCoverage) { 91cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("%s *= (1 - atlasCoverage);", args.fOutputCoverage); 92cb93a386Sopenharmony_ci } else { 93cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("%s *= atlasCoverage;", args.fOutputCoverage); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci} 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_civoid AtlasInstancedHelper::setUniformData( 98cb93a386Sopenharmony_ci const GrGLSLProgramDataManager& pdman, 99cb93a386Sopenharmony_ci const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const { 100cb93a386Sopenharmony_ci SkASSERT(fAtlasProxy->isInstantiated()); 101cb93a386Sopenharmony_ci SkISize dimensions = fAtlasProxy->backingStoreDimensions(); 102cb93a386Sopenharmony_ci pdman.set2f(atlasAdjustUniformHandle, 1.f / dimensions.width(), 1.f / dimensions.height()); 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci} // namespace skgpu::v1 106