Flutter Engine
The Flutter Engine
DrawAtlasPathOp.cpp
Go to the documentation of this file.
1/*
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
9
19#include "src/gpu/KeyBuilder.h"
20#include "src/gpu/ResourceKey.h"
21#include "src/gpu/Swizzle.h"
44
45#include <memory>
46
48enum class GrXferBarrierFlags;
49
50using namespace skia_private;
51
52namespace {
53
54class DrawAtlasPathShader : public GrGeometryProcessor {
55public:
56 DrawAtlasPathShader(bool usesLocalCoords,
57 const skgpu::ganesh::AtlasInstancedHelper* atlasHelper,
58 const GrShaderCaps& shaderCaps)
59 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
60 , fUsesLocalCoords(usesLocalCoords)
61 , fAtlasHelper(atlasHelper)
62 , fAtlasAccess(GrSamplerState::Filter::kNearest,
63 fAtlasHelper->proxy()->backendFormat(),
64 fAtlasHelper->atlasSwizzle()) {
65 if (!shaderCaps.fVertexIDSupport) {
66 constexpr static Attribute kUnitCoordAttrib(
68 this->setVertexAttributesWithImplicitOffsets(&kUnitCoordAttrib, 1);
69 }
70 fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, SkSLType::kFloat4);
71 if (fUsesLocalCoords) {
72 fAttribs.emplace_back("affineMatrix", kFloat4_GrVertexAttribType, SkSLType::kFloat4);
73 fAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, SkSLType::kFloat2);
74 }
75 SkASSERT(fAttribs.size() == this->colorAttribIdx());
76 fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, SkSLType::kHalf4);
77 fAtlasHelper->appendInstanceAttribs(&fAttribs);
78 SkASSERT(fAttribs.size() <= kMaxInstanceAttribs);
79 this->setInstanceAttributesWithImplicitOffsets(fAttribs.data(), fAttribs.size());
80 this->setTextureSamplerCnt(1);
81 }
82
83private:
84 class Impl;
85
86 int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; }
87 const char* name() const override { return "DrawAtlasPathShader"; }
88 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder* b) const override {
89 b->addBits(1, fUsesLocalCoords, "localCoords");
90 fAtlasHelper->getKeyBits(b);
91 }
92 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
93 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
94
95 const bool fUsesLocalCoords;
96 const skgpu::ganesh::AtlasInstancedHelper* const fAtlasHelper;
97 TextureSampler fAtlasAccess;
98 constexpr static int kMaxInstanceAttribs = 6;
100};
101
102class DrawAtlasPathShader::Impl : public ProgramImpl {
103public:
104 void setData(const GrGLSLProgramDataManager& pdman,
105 const GrShaderCaps&,
106 const GrGeometryProcessor& geomProc) override {
107 auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().fAtlasHelper;
108 atlasHelper->setUniformData(pdman, fAtlasAdjustUniform);
109 }
110
111private:
112 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
113 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
114 args.fVaryingHandler->emitAttributes(shader);
115
116 if (args.fShaderCaps->fVertexIDSupport) {
117 // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex
118 // attrib.
119 args.fVertBuilder->codeAppendf(R"(
120 float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
121 }
122
123 args.fVertBuilder->codeAppendf(R"(
124 float2 devCoord = mix(fillBounds.xy, fillBounds.zw, unitCoord);)");
125 gpArgs->fPositionVar.set(SkSLType::kFloat2, "devCoord");
126
127 if (shader.fUsesLocalCoords) {
128 args.fVertBuilder->codeAppendf(R"(
129 float2x2 M = float2x2(affineMatrix.xy, affineMatrix.zw);
130 float2 localCoord = inverse(M) * (devCoord - translate);)");
131 gpArgs->fLocalCoordVar.set(SkSLType::kFloat2, "localCoord");
132 }
133
134 args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage);
135 shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform);
136
137 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
138 args.fVaryingHandler->addPassThroughAttribute(
139 shader.fAttribs[shader.colorAttribIdx()].asShaderVar(),
140 args.fOutputColor,
142 }
143
144 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
145};
146
147std::unique_ptr<GrGeometryProcessor::ProgramImpl> DrawAtlasPathShader::makeProgramImpl(
148 const GrShaderCaps&) const {
149 return std::make_unique<Impl>();
150}
151
152} // anonymous namespace
153
154namespace skgpu::ganesh {
155
157 GrClampType clampType) {
158 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
160 &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance->fColor);
161 fUsesLocalCoords = analysis.usesLocalCoords();
162 return analysis;
163}
164
166 auto that = op->cast<DrawAtlasPathOp>();
167
168 if (!fAtlasHelper.isCompatible(that->fAtlasHelper) ||
169 fProcessors != that->fProcessors) {
171 }
172
173 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
174 *fTailInstance = that->fHeadInstance;
175 fTailInstance = that->fTailInstance;
176 fInstanceCount += that->fInstanceCount;
178}
179
180void DrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena,
181 const GrSurfaceProxyView& writeView, bool usesMSAASurface,
182 GrAppliedClip&& appliedClip,
183 const GrDstProxyView& dstProxyView,
184 GrXferBarrierFlags renderPassXferBarriers,
185 GrLoadOp colorLoadOp) {
186 SkASSERT(!fProgram);
187 GrPipeline::InitArgs initArgs;
188 initArgs.fCaps = &caps;
189 initArgs.fDstProxyView = dstProxyView;
190 initArgs.fWriteSwizzle = writeView.swizzle();
191 auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
192 std::move(appliedClip));
193 auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper,
194 *caps.shaderCaps());
195 fProgram = arena->make<GrProgramInfo>(caps, writeView, usesMSAASurface, pipeline,
198 renderPassXferBarriers, colorLoadOp);
199}
200
202 const GrSurfaceProxyView& writeView,
203 GrAppliedClip* appliedClip, const GrDstProxyView& dstProxyView,
204 GrXferBarrierFlags renderPassXferBarriers,
205 GrLoadOp colorLoadOp) {
206 // DMSAA is not supported on DDL.
207 bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
208 this->prepareProgram(*rContext->priv().caps(), rContext->priv().recordTimeAllocator(),
209 writeView, usesMSAASurface, std::move(*appliedClip), dstProxyView,
210 renderPassXferBarriers, colorLoadOp);
211 SkASSERT(fProgram);
212 rContext->priv().recordProgramInfo(fProgram);
213}
214
216
218 if (!fProgram) {
219 this->prepareProgram(flushState->caps(), flushState->allocator(), flushState->writeView(),
220 flushState->usesMSAASurface(), flushState->detachAppliedClip(),
221 flushState->dstProxyView(), flushState->renderPassBarriers(),
222 flushState->colorLoadOp());
223 SkASSERT(fProgram);
224 }
225
226 if (VertexWriter instanceWriter = flushState->makeVertexWriter(
227 fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer,
228 &fBaseInstance)) {
229 for (const Instance* i = fHeadInstance; i; i = i->fNext) {
230 instanceWriter << SkRect::Make(i->fFillBounds)
231 << VertexWriter::If(fUsesLocalCoords,
232 i->fLocalToDeviceIfUsingLocalCoords)
233 << i->fColor;
234 fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance);
235 }
236 }
237
238 if (!flushState->caps().shaderCaps()->fVertexIDSupport) {
239 constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};
240
241 SKGPU_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
242
243 fVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
244 GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
245 }
246}
247
248void DrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
249 if (fProgram->geomProc().hasVertexAttributes() && !fVertexBufferIfNoIDSupport) {
250 return;
251 }
252 flushState->bindPipelineAndScissorClip(*fProgram, this->bounds());
253 flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline());
254 flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport);
255 flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
256}
257
258} // namespace skgpu::ganesh
GrClampType
Definition: GrTypesPriv.h:228
GrLoadOp
Definition: GrTypesPriv.h:155
@ kFloat2_GrVertexAttribType
Definition: GrTypesPriv.h:314
@ kFloat4_GrVertexAttribType
Definition: GrTypesPriv.h:316
GrXferBarrierFlags
#define SKGPU_DEFINE_STATIC_UNIQUE_KEY(name)
Definition: ResourceKey.h:324
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
SkFilterMode
const GrCaps * caps() const
Definition: GrCaps.h:57
const GrShaderCaps * shaderCaps() const
Definition: GrCaps.h:63
GrGLSLProgramDataManager::UniformHandle UniformHandle
size_t instanceStride() const
bool hasVertexAttributes() const
skgpu::VertexWriter makeVertexWriter(size_t vertexSize, int vertexCount, sk_sp< const GrBuffer > *, int *startVertex)
GrLoadOp colorLoadOp() const final
const GrDstProxyView & dstProxyView() const final
GrXferBarrierFlags renderPassBarriers() const final
SkArenaAlloc * allocator() override
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindBuffers(sk_sp< const GrBuffer > indexBuffer, sk_sp< const GrBuffer > instanceBuffer, sk_sp< const GrBuffer > vertexBuffer, GrPrimitiveRestart primitiveRestart=GrPrimitiveRestart::kNo)
const GrSurfaceProxyView & writeView() const final
void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex)
GrResourceProvider * resourceProvider() const final
GrAppliedClip detachAppliedClip() final
const GrCaps & caps() const final
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
bool usesMSAASurface() const final
Definition: GrOp.h:70
CombineResult
Definition: GrOp.h:99
const T & cast() const
Definition: GrOp.h:148
const SkRect & bounds() const
Definition: GrOp.h:122
bool usesLocalCoords() const
Analysis finalize(const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage, const GrAppliedClip *, const GrUserStencilSettings *, const GrCaps &, GrClampType, SkPMColor4f *inputColorOverride)
const T & cast() const
Definition: GrProcessor.h:127
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
void recordProgramInfo(const GrProgramInfo *programInfo)
SkArenaAlloc * recordTimeAllocator()
GrRecordingContextPriv priv()
sk_sp< const GrGpuBuffer > findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size, const skgpu::UniqueKey &key, InitializeBufferFn)
skgpu::Swizzle swizzle() const
GrRenderTargetProxy * asRenderTargetProxy() const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
void setUniformData(const GrGLSLProgramDataManager &, const GrGLSLUniformHandler::UniformHandle &atlasAdjustUniformHandle) const
bool isCompatible(const AtlasInstancedHelper &helper)
void onPrePrepare(GrRecordingContext *, const GrSurfaceProxyView &writeView, GrAppliedClip *, const GrDstProxyView &, GrXferBarrierFlags, GrLoadOp colorLoadOp) override
GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType) override
void onExecute(GrOpFlushState *, const SkRect &chainBounds) override
CombineResult onCombineIfPossible(GrOp *, SkArenaAlloc *, const GrCaps &) override
void onPrepare(GrOpFlushState *) override
static bool b
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey)
skgpu::Swizzle fWriteSwizzle
Definition: GrPipeline.h:66
const GrCaps * fCaps
Definition: GrPipeline.h:64
GrDstProxyView fDstProxyView
Definition: GrPipeline.h:65
bool fVertexIDSupport
Definition: GrShaderCaps.h:36
static const GrUserStencilSettings & kUnused
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
static Conditional< T > If(bool condition, const T &value)
Definition: BufferWriter.h:153