blob: 101fa76365588f9b563463bd381e0a9fdfa807bd [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"
13#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
14#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
15#include "src/gpu/glsl/GrGLSLVarying.h"
16#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
17
18namespace {
19
20constexpr static GrGeometryProcessor::Attribute kInstanceAttribs[] = {
Chris Daltond2dc8dd2020-05-19 16:32:02 -060021 {"dev_xywh", kInt4_GrVertexAttribType, kInt4_GrSLType},
22 {"atlas_xy", kInt2_GrVertexAttribType, kInt2_GrSLType},
Chris Dalton4e998532020-02-10 11:06:42 -070023 {"color", kFloat4_GrVertexAttribType, kHalf4_GrSLType},
24 {"viewmatrix_scaleskew", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
25 {"viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType}};
26
27class DrawAtlasPathShader : public GrGeometryProcessor {
28public:
29 DrawAtlasPathShader(const GrTextureProxy* atlasProxy, GrSwizzle swizzle, bool usesLocalCoords)
30 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
31 , fAtlasAccess(GrSamplerState::Filter::kNearest, atlasProxy->backendFormat(), swizzle)
32 , fAtlasDimensions(atlasProxy->backingStoreDimensions())
33 , fUsesLocalCoords(usesLocalCoords) {
34 int numInstanceAttribs = SK_ARRAY_COUNT(kInstanceAttribs);
35 if (!fUsesLocalCoords) {
36 numInstanceAttribs -= 2;
37 }
38 this->setInstanceAttributes(kInstanceAttribs, numInstanceAttribs);
39 this->setTextureSamplerCnt(1);
40 }
41
42private:
43 const char* name() const override { return "DrawAtlasPathShader"; }
44 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
45 b->add32(fUsesLocalCoords);
46 }
47 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
48 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
49
50 const TextureSampler fAtlasAccess;
51 const SkISize fAtlasDimensions;
52 const bool fUsesLocalCoords;
53
54 class Impl;
55};
56
57class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
58 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040059 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
Chris Dalton4e998532020-02-10 11:06:42 -070060 args.fVaryingHandler->emitAttributes(shader);
61
62 GrGLSLVarying atlasCoord(kFloat2_GrSLType);
63 args.fVaryingHandler->addVarying("atlascoord", &atlasCoord);
64
65 GrGLSLVarying color(kHalf4_GrSLType);
John Stiles4d7ac492021-03-09 20:16:43 -050066 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
Chris Dalton4e998532020-02-10 11:06:42 -070067 args.fVaryingHandler->addPassThroughAttribute(
68 kInstanceAttribs[2], args.fOutputColor,
69 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
70
71 const char* atlasAdjust;
72 fAtlasAdjustUniform = args.fUniformHandler->addUniform(
Ethan Nicholas16464c32020-04-06 13:53:05 -040073 nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjust);
Chris Dalton4e998532020-02-10 11:06:42 -070074
75 args.fVertBuilder->codeAppendf(R"(
76 float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
Chris Daltond2dc8dd2020-05-19 16:32:02 -060077 float2 devtopleft = float2(dev_xywh.xy);
78 float2 devcoord = abs(float2(dev_xywh.zw)) * T + devtopleft;
79 float2 atlascoord = devcoord - devtopleft;
80 if (dev_xywh.w < 0) { // Negative height indicates that the path is transposed.
81 atlascoord = atlascoord.yx;
82 }
John Stilesaf9b58e2021-01-13 17:48:36 -050083 atlascoord += float2(atlas_xy);
Chris Dalton4e998532020-02-10 11:06:42 -070084 %s = atlascoord * %s;)",
85 atlasCoord.vsOut(), atlasAdjust);
86
87 gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
88
Chris Dalton4e998532020-02-10 11:06:42 -070089 if (shader.fUsesLocalCoords) {
90 args.fVertBuilder->codeAppendf(R"(
91 float2x2 M = float2x2(viewmatrix_scaleskew);
92 float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)");
Michael Ludwig553db622020-06-19 10:47:30 -040093 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
Chris Dalton4e998532020-02-10 11:06:42 -070094 }
Chris Dalton4e998532020-02-10 11:06:42 -070095
John Stiles4d7ac492021-03-09 20:16:43 -050096 args.fFragBuilder->codeAppendf("half4 %s = ", args.fOutputCoverage);
Chris Dalton4e998532020-02-10 11:06:42 -070097 args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
98 args.fFragBuilder->codeAppendf(".aaaa;");
99 }
100
Brian Osman609f1592020-07-01 15:14:39 -0400101 void setData(const GrGLSLProgramDataManager& pdman,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400102 const GrGeometryProcessor& geomProc) override {
103 const SkISize& dimensions = geomProc.cast<DrawAtlasPathShader>().fAtlasDimensions;
Chris Dalton4e998532020-02-10 11:06:42 -0700104 pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
Chris Dalton4e998532020-02-10 11:06:42 -0700105 }
106
107 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
108};
109
110GrGLSLPrimitiveProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const {
111 return new Impl();
112}
113
114} // namespace
115
116GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
117 bool hasMixedSampledCoverage,
118 GrClampType clampType) {
119 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
120 fInstanceList.fInstance.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
121 &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType,
122 &fInstanceList.fInstance.fColor);
123 fUsesLocalCoords = analysis.usesLocalCoords();
124 return analysis;
125}
126
127GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(
Herb Derbye25c3002020-10-27 15:57:27 -0400128 GrOp* op, SkArenaAlloc* alloc, const GrCaps&) {
Chris Dalton4e998532020-02-10 11:06:42 -0700129 auto* that = op->cast<GrDrawAtlasPathOp>();
130 SkASSERT(fAtlasProxy == that->fAtlasProxy);
131 SkASSERT(fEnableHWAA == that->fEnableHWAA);
132
133 if (fProcessors != that->fProcessors) {
134 return CombineResult::kCannotCombine;
135 }
136
137 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
Herb Derbye25c3002020-10-27 15:57:27 -0400138 auto* copy = alloc->make<InstanceList>(that->fInstanceList);
Chris Dalton4e998532020-02-10 11:06:42 -0700139 *fInstanceTail = copy;
140 fInstanceTail = (!copy->fNext) ? &copy->fNext : that->fInstanceTail;
141 fInstanceCount += that->fInstanceCount;
142 return CombineResult::kMerged;
143}
144
Robert Phillipsc655c3a2020-03-18 13:23:45 -0400145void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext*,
Adlai Hollere2296f72020-11-19 13:41:26 -0500146 const GrSurfaceProxyView& writeView,
Robert Phillipsc655c3a2020-03-18 13:23:45 -0400147 GrAppliedClip*,
Greg Danield358cbe2020-09-11 09:33:54 -0400148 const GrXferProcessor::DstProxyView&,
Greg Daniel42dbca52020-11-20 10:22:43 -0500149 GrXferBarrierFlags renderPassXferBarriers,
150 GrLoadOp colorLoadOp) {}
Robert Phillipsc655c3a2020-03-18 13:23:45 -0400151
Chris Dalton4e998532020-02-10 11:06:42 -0700152void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) {
153 size_t instanceStride = Instance::Stride(fUsesLocalCoords);
154 if (char* instanceData = (char*)state->makeVertexSpace(
155 instanceStride, fInstanceCount, &fInstanceBuffer, &fBaseInstance)) {
156 SkDEBUGCODE(char* end = instanceData + fInstanceCount * instanceStride);
157 for (const InstanceList* list = &fInstanceList; list; list = list->fNext) {
158 memcpy(instanceData, &list->fInstance, instanceStride);
159 instanceData += instanceStride;
160 }
161 SkASSERT(instanceData == end);
162 }
163}
164
165void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
166 SkASSERT(fAtlasProxy->isInstantiated());
167
168 GrPipeline::InitArgs initArgs;
169 if (fEnableHWAA) {
170 initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
171 }
172 initArgs.fCaps = &state->caps();
173 initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
Adlai Hollere2296f72020-11-19 13:41:26 -0500174 initArgs.fWriteSwizzle = state->drawOpArgs().writeView().swizzle();
Chris Daltonaa0e45c2020-03-16 10:05:11 -0600175 GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip());
Chris Dalton4e998532020-02-10 11:06:42 -0700176
177 GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(),
178 GrColorType::kAlpha_8);
Chris Dalton012f8492020-03-05 11:49:15 -0700179
Chris Dalton4e998532020-02-10 11:06:42 -0700180 DrawAtlasPathShader shader(fAtlasProxy.get(), swizzle, fUsesLocalCoords);
181 SkASSERT(shader.instanceStride() == Instance::Stride(fUsesLocalCoords));
182
Robert Phillips5c809642020-11-20 12:28:45 -0500183 GrProgramInfo programInfo(state->writeView(), &pipeline, &GrUserStencilSettings::kUnused,
184 &shader, GrPrimitiveType::kTriangleStrip, 0,
185 state->renderPassBarriers(), state->colorLoadOp());
Chris Dalton4e998532020-02-10 11:06:42 -0700186
Chris Daltonaa0e45c2020-03-16 10:05:11 -0600187 state->bindPipelineAndScissorClip(programInfo, this->bounds());
188 state->bindTextures(shader, *fAtlasProxy, pipeline);
Greg Daniel426274b2020-07-20 11:37:38 -0400189 state->bindBuffers(nullptr, std::move(fInstanceBuffer), nullptr);
Chris Daltonaa0e45c2020-03-16 10:05:11 -0600190 state->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
Chris Dalton4e998532020-02-10 11:06:42 -0700191}