blob: a850bc874dc1eb6fb20666b814460e944e223f7f [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"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040013#include "src/gpu/GrResourceProvider.h"
Chris Daltonbaae2dd2021-06-25 14:52:49 -060014#include "src/gpu/GrVertexWriter.h"
Chris Dalton4e998532020-02-10 11:06:42 -070015#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
16#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
17#include "src/gpu/glsl/GrGLSLVarying.h"
18#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
19
20namespace {
21
Chris Dalton4e998532020-02-10 11:06:42 -070022class DrawAtlasPathShader : public GrGeometryProcessor {
23public:
Chris Daltonbaae2dd2021-06-25 14:52:49 -060024 DrawAtlasPathShader(const GrTextureProxy* atlasProxy, GrSwizzle swizzle, bool isInverseFill,
Chris Daltona05ccc32021-06-29 19:42:13 -060025 bool usesLocalCoords, const GrShaderCaps& shaderCaps)
Chris Dalton4e998532020-02-10 11:06:42 -070026 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
27 , fAtlasAccess(GrSamplerState::Filter::kNearest, atlasProxy->backendFormat(), swizzle)
28 , fAtlasDimensions(atlasProxy->backingStoreDimensions())
Chris Daltonbaae2dd2021-06-25 14:52:49 -060029 , fIsInverseFill(isInverseFill)
Chris Dalton4e998532020-02-10 11:06:42 -070030 , fUsesLocalCoords(usesLocalCoords) {
Chris Dalton202441f2021-06-30 22:48:30 -060031 fAttribs.emplace_back("dev_xywh", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
32 fAttribs.emplace_back("atlas_xy", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
Chris Daltonbaae2dd2021-06-25 14:52:49 -060033 fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
34 if (fIsInverseFill) {
35 fAttribs.emplace_back("drawbounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
Chris Dalton4e998532020-02-10 11:06:42 -070036 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -060037 if (fUsesLocalCoords) {
38 fAttribs.emplace_back("viewmatrix_scaleskew", kFloat4_GrVertexAttribType,
39 kFloat4_GrSLType);
40 fAttribs.emplace_back("viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
41 }
42 this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
Chris Daltona05ccc32021-06-29 19:42:13 -060043 if (!shaderCaps.vertexIDSupport()) {
44 constexpr static Attribute kUnitCoordAttrib("unit_coord", kFloat2_GrVertexAttribType,
45 kFloat2_GrSLType);
46 this->setVertexAttributes(&kUnitCoordAttrib, 1);
47 }
Chris Dalton4e998532020-02-10 11:06:42 -070048 this->setTextureSamplerCnt(1);
49 }
50
51private:
52 const char* name() const override { return "DrawAtlasPathShader"; }
53 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
54 b->add32(fUsesLocalCoords);
55 }
56 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
Robert Phillipsf10535f2021-03-23 09:30:45 -040057 GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;
Chris Dalton4e998532020-02-10 11:06:42 -070058
59 const TextureSampler fAtlasAccess;
60 const SkISize fAtlasDimensions;
Chris Daltonbaae2dd2021-06-25 14:52:49 -060061 const bool fIsInverseFill;
Chris Dalton4e998532020-02-10 11:06:42 -070062 const bool fUsesLocalCoords;
Chris Daltonbaae2dd2021-06-25 14:52:49 -060063 SkSTArray<6, GrGeometryProcessor::Attribute> fAttribs;
Chris Dalton4e998532020-02-10 11:06:42 -070064
65 class Impl;
66};
67
68class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
69 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040070 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
Chris Dalton4e998532020-02-10 11:06:42 -070071 args.fVaryingHandler->emitAttributes(shader);
72
73 GrGLSLVarying atlasCoord(kFloat2_GrSLType);
74 args.fVaryingHandler->addVarying("atlascoord", &atlasCoord);
75
76 GrGLSLVarying color(kHalf4_GrSLType);
John Stiles4d7ac492021-03-09 20:16:43 -050077 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
Chris Dalton4e998532020-02-10 11:06:42 -070078 args.fVaryingHandler->addPassThroughAttribute(
Chris Daltonbaae2dd2021-06-25 14:52:49 -060079 shader.fAttribs[2], args.fOutputColor,
Chris Dalton4e998532020-02-10 11:06:42 -070080 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
81
82 const char* atlasAdjust;
83 fAtlasAdjustUniform = args.fUniformHandler->addUniform(
Ethan Nicholas16464c32020-04-06 13:53:05 -040084 nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
Chris Dalton4e998532020-02-10 11:06:42 -070085
Chris Daltona05ccc32021-06-29 19:42:13 -060086 if (args.fShaderCaps->vertexIDSupport()) {
87 // If we don't have sk_VertexID support then "unit_coord" already came in as a vertex
88 // attrib.
89 args.fVertBuilder->codeAppendf(R"(
90 float2 unit_coord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
91 }
92
Chris Dalton4e998532020-02-10 11:06:42 -070093 args.fVertBuilder->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -060094 float2 devtopleft = dev_xywh.xy;)");
Chris Daltonbaae2dd2021-06-25 14:52:49 -060095
96 if (shader.fIsInverseFill) {
97 args.fVertBuilder->codeAppendf(R"(
Chris Daltona05ccc32021-06-29 19:42:13 -060098 float2 devcoord = mix(drawbounds.xy, drawbounds.zw, unit_coord);)");
Chris Daltonbaae2dd2021-06-25 14:52:49 -060099 } else {
100 args.fVertBuilder->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600101 float2 devcoord = abs(dev_xywh.zw) * unit_coord + devtopleft;)");
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600102 }
103
104 args.fVertBuilder->codeAppendf(R"(
105 float2 atlascoord = devcoord - devtopleft;
106 bool transposed = dev_xywh.w < 0; // Negative height means the path is transposed.
107 if (transposed) {
108 atlascoord = atlascoord.yx;
109 }
Chris Dalton202441f2021-06-30 22:48:30 -0600110 atlascoord += atlas_xy;
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600111 %s = atlascoord * %s;)",
112 atlasCoord.vsOut(), atlasAdjust);
Chris Dalton4e998532020-02-10 11:06:42 -0700113
114 gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
115
Chris Dalton4e998532020-02-10 11:06:42 -0700116 if (shader.fUsesLocalCoords) {
117 args.fVertBuilder->codeAppendf(R"(
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600118 float2x2 M = float2x2(viewmatrix_scaleskew);
119 float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)");
Michael Ludwig553db622020-06-19 10:47:30 -0400120 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
Chris Dalton4e998532020-02-10 11:06:42 -0700121 }
Chris Dalton4e998532020-02-10 11:06:42 -0700122
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600123 if (shader.fIsInverseFill) {
124 GrGLSLVarying atlasBounds(kFloat4_GrSLType);
125 args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds,
126 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
127 args.fVertBuilder->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600128 float2 atlas_wh = (transposed) ? abs(dev_xywh.wz) : dev_xywh.zw;
129 %s = (atlas_xy.xyxy + atlas_wh.00xy) * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjust);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600130
131 args.fFragBuilder->codeAppendf(R"(
132 half coverage = 0;
133 float2 atlascoord = %s;
134 float4 atlasbounds = %s;
135 if (all(greaterThan(atlascoord, atlasbounds.xy)) &&
136 all(lessThan(atlascoord, atlasbounds.zw))) {
137 coverage = )", atlasCoord.fsIn(), atlasBounds.fsIn());
138 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlascoord");
139 args.fFragBuilder->codeAppendf(R"(.a;
140 }
141 half4 %s = half4(1 - coverage);)", args.fOutputCoverage);
142 } else {
143 args.fFragBuilder->codeAppendf("half4 %s = ", args.fOutputCoverage);
144 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
145 args.fFragBuilder->codeAppendf(".aaaa;");
146 }
Chris Dalton4e998532020-02-10 11:06:42 -0700147 }
148
Brian Osman609f1592020-07-01 15:14:39 -0400149 void setData(const GrGLSLProgramDataManager& pdman,
Brian Salomon5a328282021-04-14 10:32:25 -0400150 const GrShaderCaps&,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400151 const GrGeometryProcessor& geomProc) override {
152 const SkISize& dimensions = geomProc.cast<DrawAtlasPathShader>().fAtlasDimensions;
Chris Dalton4e998532020-02-10 11:06:42 -0700153 pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
Chris Dalton4e998532020-02-10 11:06:42 -0700154 }
155
156 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
157};
158
Robert Phillipsf10535f2021-03-23 09:30:45 -0400159GrGLSLGeometryProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const {
Chris Dalton4e998532020-02-10 11:06:42 -0700160 return new Impl();
161}
162
163} // namespace
164
165GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
Chris Dalton4e998532020-02-10 11:06:42 -0700166 GrClampType clampType) {
167 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600168 fHeadInstance.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
169 &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance.fColor);
Chris Dalton4e998532020-02-10 11:06:42 -0700170 fUsesLocalCoords = analysis.usesLocalCoords();
171 return analysis;
172}
173
174GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(
Herb Derbye25c3002020-10-27 15:57:27 -0400175 GrOp* op, SkArenaAlloc* alloc, const GrCaps&) {
Chris Dalton4e998532020-02-10 11:06:42 -0700176 auto* that = op->cast<GrDrawAtlasPathOp>();
177 SkASSERT(fAtlasProxy == that->fAtlasProxy);
178 SkASSERT(fEnableHWAA == that->fEnableHWAA);
179
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600180 if (fIsInverseFill != that->fIsInverseFill || fProcessors != that->fProcessors) {
Chris Dalton4e998532020-02-10 11:06:42 -0700181 return CombineResult::kCannotCombine;
182 }
183
184 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600185 auto* copy = alloc->make<Instance>(that->fHeadInstance);
186 *fTailInstance = copy;
187 fTailInstance = (!copy->fNext) ? &copy->fNext : that->fTailInstance;
Chris Dalton4e998532020-02-10 11:06:42 -0700188 fInstanceCount += that->fInstanceCount;
189 return CombineResult::kMerged;
190}
191
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600192void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView& writeView,
193 GrAppliedClip*, const GrDstProxyView&,
Greg Daniel42dbca52020-11-20 10:22:43 -0500194 GrXferBarrierFlags renderPassXferBarriers,
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600195 GrLoadOp colorLoadOp) {
196 SK_ABORT("DDL support not implemented for GrDrawAtlasPathOp.");
Chris Dalton4e998532020-02-10 11:06:42 -0700197}
198
Chris Daltona05ccc32021-06-29 19:42:13 -0600199GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
200
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600201void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) {
202 SkArenaAlloc* arena = state->allocator();
Chris Dalton4e998532020-02-10 11:06:42 -0700203
204 GrPipeline::InitArgs initArgs;
205 if (fEnableHWAA) {
206 initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
207 }
208 initArgs.fCaps = &state->caps();
209 initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
Adlai Hollere2296f72020-11-19 13:41:26 -0500210 initArgs.fWriteSwizzle = state->drawOpArgs().writeView().swizzle();
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600211 auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
212 state->detachAppliedClip());
Chris Dalton4e998532020-02-10 11:06:42 -0700213 GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(),
214 GrColorType::kAlpha_8);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600215 auto shader = arena->make<DrawAtlasPathShader>(fAtlasProxy.get(), swizzle, fIsInverseFill,
Chris Daltona05ccc32021-06-29 19:42:13 -0600216 fUsesLocalCoords, *state->caps().shaderCaps());
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600217 fProgram = arena->make<GrProgramInfo>(state->writeView(), pipeline,
218 &GrUserStencilSettings::kUnused, shader,
219 GrPrimitiveType::kTriangleStrip, 0,
220 state->renderPassBarriers(), state->colorLoadOp());
Chris Dalton012f8492020-03-05 11:49:15 -0700221
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600222 if (GrVertexWriter instanceWriter = state->makeVertexSpace(
223 shader->instanceStride(), fInstanceCount, &fInstanceBuffer, &fBaseInstance)) {
224 for (const Instance* instance = &fHeadInstance; instance; instance = instance->fNext) {
225 instanceWriter.write(
Chris Dalton202441f2021-06-30 22:48:30 -0600226 (float)instance->fDevXYWH[0],
227 (float)instance->fDevXYWH[1],
228 (float)instance->fDevXYWH[2],
229 (float)instance->fDevXYWH[3],
230 (float)instance->fAtlasXY.x(),
231 (float)instance->fAtlasXY.y(),
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600232 instance->fColor,
233 GrVertexWriter::If(fIsInverseFill, instance->fDrawBoundsIfInverseFilled),
234 GrVertexWriter::If(fUsesLocalCoords, instance->fViewMatrixIfUsingLocalCoords));
235 }
236 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600237
238 if (!state->caps().shaderCaps()->vertexIDSupport()) {
239 constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};
240
241 GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
242
243 fVertexBufferIfNoIDSupport = state->resourceProvider()->findOrMakeStaticBuffer(
244 GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
245 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600246}
Chris Dalton4e998532020-02-10 11:06:42 -0700247
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600248void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
249 SkASSERT(fAtlasProxy->isInstantiated());
250 state->bindPipelineAndScissorClip(*fProgram, this->bounds());
251 state->bindTextures(fProgram->geomProc(), *fAtlasProxy, fProgram->pipeline());
Chris Daltona05ccc32021-06-29 19:42:13 -0600252 state->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport);
Chris Daltonaa0e45c2020-03-16 10:05:11 -0600253 state->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
Chris Dalton4e998532020-02-10 11:06:42 -0700254}