blob: 78c5253350f31b93a9002650fbbc1f7eb79df5d8 [file] [log] [blame]
Chris Dalton4e998532020-02-10 11:06:42 -07001/*
2 * Copyright 2020 Google Inc.
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/tessellate/GrDrawAtlasPathOp.h"
9
10#include "src/gpu/GrOpFlushState.h"
11#include "src/gpu/GrOpsRenderPass.h"
12#include "src/gpu/GrProgramInfo.h"
Chris Daltonbaae2dd2021-06-25 14:52:49 -060013#include "src/gpu/GrVertexWriter.h"
Chris Dalton4e998532020-02-10 11:06:42 -070014#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
15#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
16#include "src/gpu/glsl/GrGLSLVarying.h"
17#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
18
19namespace {
20
Chris Dalton4e998532020-02-10 11:06:42 -070021class DrawAtlasPathShader : public GrGeometryProcessor {
22public:
Chris Daltonbaae2dd2021-06-25 14:52:49 -060023 DrawAtlasPathShader(const GrTextureProxy* atlasProxy, GrSwizzle swizzle, bool isInverseFill,
24 bool usesLocalCoords)
Chris Dalton4e998532020-02-10 11:06:42 -070025 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
26 , fAtlasAccess(GrSamplerState::Filter::kNearest, atlasProxy->backendFormat(), swizzle)
27 , fAtlasDimensions(atlasProxy->backingStoreDimensions())
Chris Daltonbaae2dd2021-06-25 14:52:49 -060028 , fIsInverseFill(isInverseFill)
Chris Dalton4e998532020-02-10 11:06:42 -070029 , fUsesLocalCoords(usesLocalCoords) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060030 fAttribs.emplace_back("dev_xywh", kInt4_GrVertexAttribType, kInt4_GrSLType);
31 fAttribs.emplace_back("atlas_xy", kInt2_GrVertexAttribType, kInt2_GrSLType);
32 fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
33 if (fIsInverseFill) {
34 fAttribs.emplace_back("drawbounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
Chris Dalton4e998532020-02-10 11:06:42 -070035 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -060036 if (fUsesLocalCoords) {
37 fAttribs.emplace_back("viewmatrix_scaleskew", kFloat4_GrVertexAttribType,
38 kFloat4_GrSLType);
39 fAttribs.emplace_back("viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
40 }
41 this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
Chris Dalton4e998532020-02-10 11:06:42 -070042 this->setTextureSamplerCnt(1);
43 }
44
45private:
46 const char* name() const override { return "DrawAtlasPathShader"; }
47 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
48 b->add32(fUsesLocalCoords);
49 }
50 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
Robert Phillipsf10535f2021-03-23 09:30:45 -040051 GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;
Chris Dalton4e998532020-02-10 11:06:42 -070052
53 const TextureSampler fAtlasAccess;
54 const SkISize fAtlasDimensions;
Chris Daltonbaae2dd2021-06-25 14:52:49 -060055 const bool fIsInverseFill;
Chris Dalton4e998532020-02-10 11:06:42 -070056 const bool fUsesLocalCoords;
Chris Daltonbaae2dd2021-06-25 14:52:49 -060057 SkSTArray<6, GrGeometryProcessor::Attribute> fAttribs;
Chris Dalton4e998532020-02-10 11:06:42 -070058
59 class Impl;
60};
61
62class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
63 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040064 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
Chris Dalton4e998532020-02-10 11:06:42 -070065 args.fVaryingHandler->emitAttributes(shader);
66
67 GrGLSLVarying atlasCoord(kFloat2_GrSLType);
68 args.fVaryingHandler->addVarying("atlascoord", &atlasCoord);
69
70 GrGLSLVarying color(kHalf4_GrSLType);
John Stiles4d7ac492021-03-09 20:16:43 -050071 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
Chris Dalton4e998532020-02-10 11:06:42 -070072 args.fVaryingHandler->addPassThroughAttribute(
Chris Daltonbaae2dd2021-06-25 14:52:49 -060073 shader.fAttribs[2], args.fOutputColor,
Chris Dalton4e998532020-02-10 11:06:42 -070074 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
75
76 const char* atlasAdjust;
77 fAtlasAdjustUniform = args.fUniformHandler->addUniform(
Ethan Nicholas16464c32020-04-06 13:53:05 -040078 nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
Chris Dalton4e998532020-02-10 11:06:42 -070079
80 args.fVertBuilder->codeAppendf(R"(
Chris Daltonbaae2dd2021-06-25 14:52:49 -060081 float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
82 float2 devtopleft = float2(dev_xywh.xy);)");
83
84 if (shader.fIsInverseFill) {
85 args.fVertBuilder->codeAppendf(R"(
86 float2 devcoord = mix(drawbounds.xy, drawbounds.zw, T);)");
87 } else {
88 args.fVertBuilder->codeAppendf(R"(
89 float2 devcoord = abs(float2(dev_xywh.zw)) * T + devtopleft;)");
90 }
91
92 args.fVertBuilder->codeAppendf(R"(
93 float2 atlascoord = devcoord - devtopleft;
94 bool transposed = dev_xywh.w < 0; // Negative height means the path is transposed.
95 if (transposed) {
96 atlascoord = atlascoord.yx;
97 }
98 atlascoord += float2(atlas_xy);
99 %s = atlascoord * %s;)",
100 atlasCoord.vsOut(), atlasAdjust);
Chris Dalton4e998532020-02-10 11:06:42 -0700101
102 gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
103
Chris Dalton4e998532020-02-10 11:06:42 -0700104 if (shader.fUsesLocalCoords) {
105 args.fVertBuilder->codeAppendf(R"(
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600106 float2x2 M = float2x2(viewmatrix_scaleskew);
107 float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)");
Michael Ludwig553db622020-06-19 10:47:30 -0400108 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
Chris Dalton4e998532020-02-10 11:06:42 -0700109 }
Chris Dalton4e998532020-02-10 11:06:42 -0700110
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600111 if (shader.fIsInverseFill) {
112 GrGLSLVarying atlasBounds(kFloat4_GrSLType);
113 args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds,
114 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
115 args.fVertBuilder->codeAppendf(R"(
116 int2 atlas_wh = (transposed) ? abs(dev_xywh.wz) : dev_xywh.zw;
117 %s = float4(atlas_xy, atlas_xy + atlas_wh) * %s.xyxy;)", atlasBounds.vsOut(),
118 atlasAdjust);
119
120 args.fFragBuilder->codeAppendf(R"(
121 half coverage = 0;
122 float2 atlascoord = %s;
123 float4 atlasbounds = %s;
124 if (all(greaterThan(atlascoord, atlasbounds.xy)) &&
125 all(lessThan(atlascoord, atlasbounds.zw))) {
126 coverage = )", atlasCoord.fsIn(), atlasBounds.fsIn());
127 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlascoord");
128 args.fFragBuilder->codeAppendf(R"(.a;
129 }
130 half4 %s = half4(1 - coverage);)", args.fOutputCoverage);
131 } else {
132 args.fFragBuilder->codeAppendf("half4 %s = ", args.fOutputCoverage);
133 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
134 args.fFragBuilder->codeAppendf(".aaaa;");
135 }
Chris Dalton4e998532020-02-10 11:06:42 -0700136 }
137
Brian Osman609f1592020-07-01 15:14:39 -0400138 void setData(const GrGLSLProgramDataManager& pdman,
Brian Salomon5a328282021-04-14 10:32:25 -0400139 const GrShaderCaps&,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400140 const GrGeometryProcessor& geomProc) override {
141 const SkISize& dimensions = geomProc.cast<DrawAtlasPathShader>().fAtlasDimensions;
Chris Dalton4e998532020-02-10 11:06:42 -0700142 pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
Chris Dalton4e998532020-02-10 11:06:42 -0700143 }
144
145 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
146};
147
Robert Phillipsf10535f2021-03-23 09:30:45 -0400148GrGLSLGeometryProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const {
Chris Dalton4e998532020-02-10 11:06:42 -0700149 return new Impl();
150}
151
152} // namespace
153
154GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
Chris Dalton4e998532020-02-10 11:06:42 -0700155 GrClampType clampType) {
156 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600157 fHeadInstance.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
158 &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance.fColor);
Chris Dalton4e998532020-02-10 11:06:42 -0700159 fUsesLocalCoords = analysis.usesLocalCoords();
160 return analysis;
161}
162
163GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(
Herb Derbye25c3002020-10-27 15:57:27 -0400164 GrOp* op, SkArenaAlloc* alloc, const GrCaps&) {
Chris Dalton4e998532020-02-10 11:06:42 -0700165 auto* that = op->cast<GrDrawAtlasPathOp>();
166 SkASSERT(fAtlasProxy == that->fAtlasProxy);
167 SkASSERT(fEnableHWAA == that->fEnableHWAA);
168
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600169 if (fIsInverseFill != that->fIsInverseFill || fProcessors != that->fProcessors) {
Chris Dalton4e998532020-02-10 11:06:42 -0700170 return CombineResult::kCannotCombine;
171 }
172
173 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600174 auto* copy = alloc->make<Instance>(that->fHeadInstance);
175 *fTailInstance = copy;
176 fTailInstance = (!copy->fNext) ? &copy->fNext : that->fTailInstance;
Chris Dalton4e998532020-02-10 11:06:42 -0700177 fInstanceCount += that->fInstanceCount;
178 return CombineResult::kMerged;
179}
180
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600181void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView& writeView,
182 GrAppliedClip*, const GrDstProxyView&,
Greg Daniel42dbca52020-11-20 10:22:43 -0500183 GrXferBarrierFlags renderPassXferBarriers,
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600184 GrLoadOp colorLoadOp) {
185 SK_ABORT("DDL support not implemented for GrDrawAtlasPathOp.");
Chris Dalton4e998532020-02-10 11:06:42 -0700186}
187
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600188void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) {
189 SkArenaAlloc* arena = state->allocator();
Chris Dalton4e998532020-02-10 11:06:42 -0700190
191 GrPipeline::InitArgs initArgs;
192 if (fEnableHWAA) {
193 initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
194 }
195 initArgs.fCaps = &state->caps();
196 initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
Adlai Hollere2296f72020-11-19 13:41:26 -0500197 initArgs.fWriteSwizzle = state->drawOpArgs().writeView().swizzle();
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600198 auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
199 state->detachAppliedClip());
Chris Dalton4e998532020-02-10 11:06:42 -0700200 GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(),
201 GrColorType::kAlpha_8);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600202 auto shader = arena->make<DrawAtlasPathShader>(fAtlasProxy.get(), swizzle, fIsInverseFill,
203 fUsesLocalCoords);
204 fProgram = arena->make<GrProgramInfo>(state->writeView(), pipeline,
205 &GrUserStencilSettings::kUnused, shader,
206 GrPrimitiveType::kTriangleStrip, 0,
207 state->renderPassBarriers(), state->colorLoadOp());
Chris Dalton012f8492020-03-05 11:49:15 -0700208
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600209 if (GrVertexWriter instanceWriter = state->makeVertexSpace(
210 shader->instanceStride(), fInstanceCount, &fInstanceBuffer, &fBaseInstance)) {
211 for (const Instance* instance = &fHeadInstance; instance; instance = instance->fNext) {
212 instanceWriter.write(
213 instance->fDevXYWH,
214 instance->fAtlasXY,
215 instance->fColor,
216 GrVertexWriter::If(fIsInverseFill, instance->fDrawBoundsIfInverseFilled),
217 GrVertexWriter::If(fUsesLocalCoords, instance->fViewMatrixIfUsingLocalCoords));
218 }
219 }
220}
Chris Dalton4e998532020-02-10 11:06:42 -0700221
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600222void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
223 SkASSERT(fAtlasProxy->isInstantiated());
224 state->bindPipelineAndScissorClip(*fProgram, this->bounds());
225 state->bindTextures(fProgram->geomProc(), *fAtlasProxy, fProgram->pipeline());
Greg Daniel426274b2020-07-20 11:37:38 -0400226 state->bindBuffers(nullptr, std::move(fInstanceBuffer), nullptr);
Chris Daltonaa0e45c2020-03-16 10:05:11 -0600227 state->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
Chris Dalton4e998532020-02-10 11:06:42 -0700228}