1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/TriangulatingPathRenderer.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkIDChangeListener.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMessageBus.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAppliedClip.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAuditTrail.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDefaultGeoProcFactory.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDrawOpTest.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrEagerVertexAllocator.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrMeshDrawTarget.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpFlushState.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPaint.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorAnalysis.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorSet.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSimpleMesh.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStyle.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrThreadSafeCache.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrAATriangulator.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrPathUtils.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrStyledShape.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrTriangulator.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrMeshDrawOp.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelperWithStencil.h"
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTestUtils.h"
59*c8dee2aaSAndroid Build Coastguard Worker #endif
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker #include <array>
62*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
63*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
64*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker class GrDstProxyView;
67*c8dee2aaSAndroid Build Coastguard Worker class GrSurfaceProxyView;
68*c8dee2aaSAndroid Build Coastguard Worker class SkArenaAlloc;
69*c8dee2aaSAndroid Build Coastguard Worker enum class GrXferBarrierFlags;
70*c8dee2aaSAndroid Build Coastguard Worker struct GrUserStencilSettings;
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_ENABLE_OPTIMIZE_SIZE)
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker #ifndef GR_AA_TESSELLATOR_MAX_VERB_COUNT
75*c8dee2aaSAndroid Build Coastguard Worker #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 10
76*c8dee2aaSAndroid Build Coastguard Worker #endif
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker /*
79*c8dee2aaSAndroid Build Coastguard Worker * This path renderer linearizes and decomposes the path into triangles using GrTriangulator,
80*c8dee2aaSAndroid Build Coastguard Worker * uploads the triangles to a vertex buffer, and renders them with a single draw call. It can do
81*c8dee2aaSAndroid Build Coastguard Worker * screenspace antialiasing with a one-pixel coverage ramp.
82*c8dee2aaSAndroid Build Coastguard Worker */
83*c8dee2aaSAndroid Build Coastguard Worker namespace {
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker // The TessInfo struct contains ancillary data not specifically required for the triangle
86*c8dee2aaSAndroid Build Coastguard Worker // data (which is stored in a GrThreadSafeCache::VertexData object).
87*c8dee2aaSAndroid Build Coastguard Worker // The 'fNumVertices' field is a temporary exception. It is still needed to support the
88*c8dee2aaSAndroid Build Coastguard Worker // AA triangulated path case - which doesn't use the GrThreadSafeCache nor the VertexData object).
89*c8dee2aaSAndroid Build Coastguard Worker // When there is an associated VertexData, its numVertices should always match the TessInfo's
90*c8dee2aaSAndroid Build Coastguard Worker // value.
91*c8dee2aaSAndroid Build Coastguard Worker struct TessInfo {
92*c8dee2aaSAndroid Build Coastguard Worker int fNumVertices;
93*c8dee2aaSAndroid Build Coastguard Worker bool fIsLinear;
94*c8dee2aaSAndroid Build Coastguard Worker SkScalar fTolerance;
95*c8dee2aaSAndroid Build Coastguard Worker };
96*c8dee2aaSAndroid Build Coastguard Worker
create_data(int numVertices,bool isLinear,SkScalar tol)97*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkData> create_data(int numVertices, bool isLinear, SkScalar tol) {
98*c8dee2aaSAndroid Build Coastguard Worker TessInfo info { numVertices, isLinear, tol };
99*c8dee2aaSAndroid Build Coastguard Worker return SkData::MakeWithCopy(&info, sizeof(info));
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker
cache_match(const SkData * data,SkScalar tol)102*c8dee2aaSAndroid Build Coastguard Worker bool cache_match(const SkData* data, SkScalar tol) {
103*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data);
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker const TessInfo* info = static_cast<const TessInfo*>(data->data());
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker return info->fIsLinear || info->fTolerance < 3.0f * tol;
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker // Should 'challenger' replace 'incumbent' in the cache if there is a collision?
is_newer_better(SkData * incumbent,SkData * challenger)111*c8dee2aaSAndroid Build Coastguard Worker bool is_newer_better(SkData* incumbent, SkData* challenger) {
112*c8dee2aaSAndroid Build Coastguard Worker const TessInfo* i = static_cast<const TessInfo*>(incumbent->data());
113*c8dee2aaSAndroid Build Coastguard Worker const TessInfo* c = static_cast<const TessInfo*>(challenger->data());
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker if (i->fIsLinear || i->fTolerance <= c->fTolerance) {
116*c8dee2aaSAndroid Build Coastguard Worker return false; // prefer the incumbent
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker
119*c8dee2aaSAndroid Build Coastguard Worker return true;
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker // When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
123*c8dee2aaSAndroid Build Coastguard Worker class UniqueKeyInvalidator : public SkIDChangeListener {
124*c8dee2aaSAndroid Build Coastguard Worker public:
UniqueKeyInvalidator(const skgpu::UniqueKey & key,uint32_t contextUniqueID)125*c8dee2aaSAndroid Build Coastguard Worker UniqueKeyInvalidator(const skgpu::UniqueKey& key, uint32_t contextUniqueID)
126*c8dee2aaSAndroid Build Coastguard Worker : fMsg(key, contextUniqueID, /* inThreadSafeCache */ true) {}
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker private:
129*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKeyInvalidatedMessage fMsg;
130*c8dee2aaSAndroid Build Coastguard Worker
changed()131*c8dee2aaSAndroid Build Coastguard Worker void changed() override {
132*c8dee2aaSAndroid Build Coastguard Worker SkMessageBus<skgpu::UniqueKeyInvalidatedMessage, uint32_t>::Post(fMsg);
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker };
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker class StaticVertexAllocator : public GrEagerVertexAllocator {
137*c8dee2aaSAndroid Build Coastguard Worker public:
StaticVertexAllocator(GrResourceProvider * resourceProvider,bool canMapVB)138*c8dee2aaSAndroid Build Coastguard Worker StaticVertexAllocator(GrResourceProvider* resourceProvider, bool canMapVB)
139*c8dee2aaSAndroid Build Coastguard Worker : fResourceProvider(resourceProvider)
140*c8dee2aaSAndroid Build Coastguard Worker , fCanMapVB(canMapVB) {
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
~StaticVertexAllocator()144*c8dee2aaSAndroid Build Coastguard Worker ~StaticVertexAllocator() override {
145*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && !fVertexData);
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker #endif
148*c8dee2aaSAndroid Build Coastguard Worker
lock(size_t stride,int eagerCount)149*c8dee2aaSAndroid Build Coastguard Worker void* lock(size_t stride, int eagerCount) override {
150*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && !fVertexData);
151*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(stride && eagerCount);
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker size_t size = eagerCount * stride;
154*c8dee2aaSAndroid Build Coastguard Worker fVertexBuffer = fResourceProvider->createBuffer(size,
155*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType::kVertex,
156*c8dee2aaSAndroid Build Coastguard Worker kStatic_GrAccessPattern,
157*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider::ZeroInit::kNo);
158*c8dee2aaSAndroid Build Coastguard Worker if (!fVertexBuffer) {
159*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker if (fCanMapVB) {
162*c8dee2aaSAndroid Build Coastguard Worker fVertices = fVertexBuffer->map();
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker if (!fVertices) {
165*c8dee2aaSAndroid Build Coastguard Worker fVertices = sk_malloc_throw(eagerCount * stride);
166*c8dee2aaSAndroid Build Coastguard Worker fCanMapVB = false;
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker fLockStride = stride;
169*c8dee2aaSAndroid Build Coastguard Worker return fVertices;
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
unlock(int actualCount)172*c8dee2aaSAndroid Build Coastguard Worker void unlock(int actualCount) override {
173*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fLockStride && fVertices && fVertexBuffer && !fVertexData);
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker if (fCanMapVB) {
176*c8dee2aaSAndroid Build Coastguard Worker fVertexBuffer->unmap();
177*c8dee2aaSAndroid Build Coastguard Worker } else {
178*c8dee2aaSAndroid Build Coastguard Worker fVertexBuffer->updateData(fVertices,
179*c8dee2aaSAndroid Build Coastguard Worker /*offset=*/0,
180*c8dee2aaSAndroid Build Coastguard Worker /*size=*/actualCount*fLockStride,
181*c8dee2aaSAndroid Build Coastguard Worker /*preserve=*/false);
182*c8dee2aaSAndroid Build Coastguard Worker sk_free(fVertices);
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker fVertexData = GrThreadSafeCache::MakeVertexData(std::move(fVertexBuffer),
186*c8dee2aaSAndroid Build Coastguard Worker actualCount, fLockStride);
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker fVertices = nullptr;
189*c8dee2aaSAndroid Build Coastguard Worker fLockStride = 0;
190*c8dee2aaSAndroid Build Coastguard Worker }
191*c8dee2aaSAndroid Build Coastguard Worker
detachVertexData()192*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafeCache::VertexData> detachVertexData() {
193*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fLockStride && !fVertices && !fVertexBuffer && fVertexData);
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker return std::move(fVertexData);
196*c8dee2aaSAndroid Build Coastguard Worker }
197*c8dee2aaSAndroid Build Coastguard Worker
198*c8dee2aaSAndroid Build Coastguard Worker private:
199*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafeCache::VertexData> fVertexData;
200*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> fVertexBuffer;
201*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* fResourceProvider;
202*c8dee2aaSAndroid Build Coastguard Worker bool fCanMapVB;
203*c8dee2aaSAndroid Build Coastguard Worker void* fVertices = nullptr;
204*c8dee2aaSAndroid Build Coastguard Worker size_t fLockStride = 0;
205*c8dee2aaSAndroid Build Coastguard Worker };
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker class TriangulatingPathOp final : public GrMeshDrawOp {
208*c8dee2aaSAndroid Build Coastguard Worker private:
209*c8dee2aaSAndroid Build Coastguard Worker using Helper = GrSimpleMeshDrawOpHelperWithStencil;
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker public:
212*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID
213*c8dee2aaSAndroid Build Coastguard Worker
Make(GrRecordingContext * context,GrPaint && paint,const GrStyledShape & shape,const SkMatrix & viewMatrix,SkIRect devClipBounds,GrAAType aaType,const GrUserStencilSettings * stencilSettings)214*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* context,
215*c8dee2aaSAndroid Build Coastguard Worker GrPaint&& paint,
216*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
217*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& viewMatrix,
218*c8dee2aaSAndroid Build Coastguard Worker SkIRect devClipBounds,
219*c8dee2aaSAndroid Build Coastguard Worker GrAAType aaType,
220*c8dee2aaSAndroid Build Coastguard Worker const GrUserStencilSettings* stencilSettings) {
221*c8dee2aaSAndroid Build Coastguard Worker return Helper::FactoryHelper<TriangulatingPathOp>(context, std::move(paint), shape,
222*c8dee2aaSAndroid Build Coastguard Worker viewMatrix, devClipBounds, aaType,
223*c8dee2aaSAndroid Build Coastguard Worker stencilSettings);
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker
name() const226*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "TriangulatingPathOp"; }
227*c8dee2aaSAndroid Build Coastguard Worker
visitProxies(const GrVisitProxyFunc & func) const228*c8dee2aaSAndroid Build Coastguard Worker void visitProxies(const GrVisitProxyFunc& func) const override {
229*c8dee2aaSAndroid Build Coastguard Worker if (fProgramInfo) {
230*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo->visitFPProxies(func);
231*c8dee2aaSAndroid Build Coastguard Worker } else {
232*c8dee2aaSAndroid Build Coastguard Worker fHelper.visitProxies(func);
233*c8dee2aaSAndroid Build Coastguard Worker }
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker
TriangulatingPathOp(GrProcessorSet * processorSet,const SkPMColor4f & color,const GrStyledShape & shape,const SkMatrix & viewMatrix,const SkIRect & devClipBounds,GrAAType aaType,const GrUserStencilSettings * stencilSettings)236*c8dee2aaSAndroid Build Coastguard Worker TriangulatingPathOp(GrProcessorSet* processorSet,
237*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& color,
238*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
239*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& viewMatrix,
240*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& devClipBounds,
241*c8dee2aaSAndroid Build Coastguard Worker GrAAType aaType,
242*c8dee2aaSAndroid Build Coastguard Worker const GrUserStencilSettings* stencilSettings)
243*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(ClassID())
244*c8dee2aaSAndroid Build Coastguard Worker , fHelper(processorSet, aaType, stencilSettings)
245*c8dee2aaSAndroid Build Coastguard Worker , fColor(color)
246*c8dee2aaSAndroid Build Coastguard Worker , fShape(shape)
247*c8dee2aaSAndroid Build Coastguard Worker , fViewMatrix(viewMatrix)
248*c8dee2aaSAndroid Build Coastguard Worker , fDevClipBounds(devClipBounds)
249*c8dee2aaSAndroid Build Coastguard Worker , fAntiAlias(GrAAType::kCoverage == aaType) {
250*c8dee2aaSAndroid Build Coastguard Worker SkRect devBounds;
251*c8dee2aaSAndroid Build Coastguard Worker viewMatrix.mapRect(&devBounds, shape.bounds());
252*c8dee2aaSAndroid Build Coastguard Worker if (shape.inverseFilled()) {
253*c8dee2aaSAndroid Build Coastguard Worker // Because the clip bounds are used to add a contour for inverse fills, they must also
254*c8dee2aaSAndroid Build Coastguard Worker // include the path bounds.
255*c8dee2aaSAndroid Build Coastguard Worker devBounds.join(SkRect::Make(fDevClipBounds));
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker this->setBounds(devBounds, HasAABloat(fAntiAlias), IsHairline::kNo);
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
fixedFunctionFlags() const260*c8dee2aaSAndroid Build Coastguard Worker FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
261*c8dee2aaSAndroid Build Coastguard Worker
finalize(const GrCaps & caps,const GrAppliedClip * clip,GrClampType clampType)262*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
263*c8dee2aaSAndroid Build Coastguard Worker GrClampType clampType) override {
264*c8dee2aaSAndroid Build Coastguard Worker GrProcessorAnalysisCoverage coverage = fAntiAlias
265*c8dee2aaSAndroid Build Coastguard Worker ? GrProcessorAnalysisCoverage::kSingleChannel
266*c8dee2aaSAndroid Build Coastguard Worker : GrProcessorAnalysisCoverage::kNone;
267*c8dee2aaSAndroid Build Coastguard Worker // This Op uses uniform (not vertex) color, so doesn't need to track wide color.
268*c8dee2aaSAndroid Build Coastguard Worker return fHelper.finalizeProcessors(caps, clip, clampType, coverage, &fColor, nullptr);
269*c8dee2aaSAndroid Build Coastguard Worker }
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker private:
getPath() const272*c8dee2aaSAndroid Build Coastguard Worker SkPath getPath() const {
273*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fShape.style().applies());
274*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
275*c8dee2aaSAndroid Build Coastguard Worker fShape.asPath(&path);
276*c8dee2aaSAndroid Build Coastguard Worker return path;
277*c8dee2aaSAndroid Build Coastguard Worker }
278*c8dee2aaSAndroid Build Coastguard Worker
CreateKey(skgpu::UniqueKey * key,const GrStyledShape & shape,const SkIRect & devClipBounds)279*c8dee2aaSAndroid Build Coastguard Worker static void CreateKey(skgpu::UniqueKey* key,
280*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
281*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& devClipBounds) {
282*c8dee2aaSAndroid Build Coastguard Worker static const skgpu::UniqueKey::Domain kDomain = skgpu::UniqueKey::GenerateDomain();
283*c8dee2aaSAndroid Build Coastguard Worker
284*c8dee2aaSAndroid Build Coastguard Worker bool inverseFill = shape.inverseFilled();
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kClipBoundsCnt = sizeof(devClipBounds) / sizeof(uint32_t);
287*c8dee2aaSAndroid Build Coastguard Worker int shapeKeyDataCnt = shape.unstyledKeySize();
288*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(shapeKeyDataCnt >= 0);
289*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey::Builder builder(key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
290*c8dee2aaSAndroid Build Coastguard Worker shape.writeUnstyledKey(&builder[0]);
291*c8dee2aaSAndroid Build Coastguard Worker // For inverse fills, the tessellation is dependent on clip bounds.
292*c8dee2aaSAndroid Build Coastguard Worker if (inverseFill) {
293*c8dee2aaSAndroid Build Coastguard Worker memcpy(&builder[shapeKeyDataCnt], &devClipBounds, sizeof(devClipBounds));
294*c8dee2aaSAndroid Build Coastguard Worker } else {
295*c8dee2aaSAndroid Build Coastguard Worker memset(&builder[shapeKeyDataCnt], 0, sizeof(devClipBounds));
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker builder.finish();
299*c8dee2aaSAndroid Build Coastguard Worker }
300*c8dee2aaSAndroid Build Coastguard Worker
301*c8dee2aaSAndroid Build Coastguard Worker // Triangulate the provided 'shape' in the shape's coordinate space. 'tol' should already
302*c8dee2aaSAndroid Build Coastguard Worker // have been mapped back from device space.
Triangulate(GrEagerVertexAllocator * allocator,const SkMatrix & viewMatrix,const GrStyledShape & shape,const SkIRect & devClipBounds,SkScalar tol,bool * isLinear)303*c8dee2aaSAndroid Build Coastguard Worker static int Triangulate(GrEagerVertexAllocator* allocator,
304*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& viewMatrix,
305*c8dee2aaSAndroid Build Coastguard Worker const GrStyledShape& shape,
306*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& devClipBounds,
307*c8dee2aaSAndroid Build Coastguard Worker SkScalar tol,
308*c8dee2aaSAndroid Build Coastguard Worker bool* isLinear) {
309*c8dee2aaSAndroid Build Coastguard Worker SkRect clipBounds = SkRect::Make(devClipBounds);
310*c8dee2aaSAndroid Build Coastguard Worker
311*c8dee2aaSAndroid Build Coastguard Worker SkMatrix vmi;
312*c8dee2aaSAndroid Build Coastguard Worker if (!viewMatrix.invert(&vmi)) {
313*c8dee2aaSAndroid Build Coastguard Worker return 0;
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker vmi.mapRect(&clipBounds);
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!shape.style().applies());
318*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
319*c8dee2aaSAndroid Build Coastguard Worker shape.asPath(&path);
320*c8dee2aaSAndroid Build Coastguard Worker
321*c8dee2aaSAndroid Build Coastguard Worker return GrTriangulator::PathToTriangles(path, tol, clipBounds, allocator, isLinear);
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker
createNonAAMesh(GrMeshDrawTarget * target)324*c8dee2aaSAndroid Build Coastguard Worker void createNonAAMesh(GrMeshDrawTarget* target) {
325*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fAntiAlias);
326*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* rp = target->resourceProvider();
327*c8dee2aaSAndroid Build Coastguard Worker auto threadSafeCache = target->threadSafeCache();
328*c8dee2aaSAndroid Build Coastguard Worker
329*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
330*c8dee2aaSAndroid Build Coastguard Worker CreateKey(&key, fShape, fDevClipBounds);
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Worker SkScalar tol = GrPathUtils::scaleToleranceToSrc(GrPathUtils::kDefaultTolerance,
333*c8dee2aaSAndroid Build Coastguard Worker fViewMatrix, fShape.bounds());
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker if (!fVertexData) {
336*c8dee2aaSAndroid Build Coastguard Worker auto [cachedVerts, data] = threadSafeCache->findVertsWithData(key);
337*c8dee2aaSAndroid Build Coastguard Worker if (cachedVerts && cache_match(data.get(), tol)) {
338*c8dee2aaSAndroid Build Coastguard Worker fVertexData = std::move(cachedVerts);
339*c8dee2aaSAndroid Build Coastguard Worker }
340*c8dee2aaSAndroid Build Coastguard Worker }
341*c8dee2aaSAndroid Build Coastguard Worker
342*c8dee2aaSAndroid Build Coastguard Worker if (fVertexData) {
343*c8dee2aaSAndroid Build Coastguard Worker if (!fVertexData->gpuBuffer()) {
344*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> buffer = rp->createBuffer(fVertexData->vertices(),
345*c8dee2aaSAndroid Build Coastguard Worker fVertexData->size(),
346*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType::kVertex,
347*c8dee2aaSAndroid Build Coastguard Worker kStatic_GrAccessPattern);
348*c8dee2aaSAndroid Build Coastguard Worker if (!buffer) {
349*c8dee2aaSAndroid Build Coastguard Worker return;
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker
352*c8dee2aaSAndroid Build Coastguard Worker // Since we have a direct context and a ref on 'fVertexData' we need not worry
353*c8dee2aaSAndroid Build Coastguard Worker // about any threading issues in this call.
354*c8dee2aaSAndroid Build Coastguard Worker fVertexData->setGpuBuffer(std::move(buffer));
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker
357*c8dee2aaSAndroid Build Coastguard Worker fMesh = CreateMesh(target, fVertexData->refGpuBuffer(), 0, fVertexData->numVertices());
358*c8dee2aaSAndroid Build Coastguard Worker return;
359*c8dee2aaSAndroid Build Coastguard Worker }
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
362*c8dee2aaSAndroid Build Coastguard Worker StaticVertexAllocator allocator(rp, canMapVB);
363*c8dee2aaSAndroid Build Coastguard Worker
364*c8dee2aaSAndroid Build Coastguard Worker bool isLinear;
365*c8dee2aaSAndroid Build Coastguard Worker int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
366*c8dee2aaSAndroid Build Coastguard Worker &isLinear);
367*c8dee2aaSAndroid Build Coastguard Worker if (vertexCount == 0) {
368*c8dee2aaSAndroid Build Coastguard Worker return;
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker fVertexData = allocator.detachVertexData();
372*c8dee2aaSAndroid Build Coastguard Worker
373*c8dee2aaSAndroid Build Coastguard Worker key.setCustomData(create_data(vertexCount, isLinear, tol));
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker auto [tmpV, tmpD] = threadSafeCache->addVertsWithData(key, fVertexData, is_newer_better);
376*c8dee2aaSAndroid Build Coastguard Worker if (tmpV != fVertexData) {
377*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!tmpV->gpuBuffer());
378*c8dee2aaSAndroid Build Coastguard Worker // In this case, although the different triangulation found in the cache is better,
379*c8dee2aaSAndroid Build Coastguard Worker // we will continue on with the current triangulation since it is already on the gpu.
380*c8dee2aaSAndroid Build Coastguard Worker } else {
381*c8dee2aaSAndroid Build Coastguard Worker // This isn't perfect. The current triangulation is in the cache but it may have
382*c8dee2aaSAndroid Build Coastguard Worker // replaced a pre-existing one. A duplicated listener is unlikely and not that
383*c8dee2aaSAndroid Build Coastguard Worker // expensive so we just roll with it.
384*c8dee2aaSAndroid Build Coastguard Worker fShape.addGenIDChangeListener(
385*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<UniqueKeyInvalidator>(key, target->contextUniqueID()));
386*c8dee2aaSAndroid Build Coastguard Worker }
387*c8dee2aaSAndroid Build Coastguard Worker
388*c8dee2aaSAndroid Build Coastguard Worker fMesh = CreateMesh(target, fVertexData->refGpuBuffer(), 0, fVertexData->numVertices());
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker
createAAMesh(GrMeshDrawTarget * target)391*c8dee2aaSAndroid Build Coastguard Worker void createAAMesh(GrMeshDrawTarget* target) {
392*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fVertexData);
393*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fAntiAlias);
394*c8dee2aaSAndroid Build Coastguard Worker SkPath path = this->getPath();
395*c8dee2aaSAndroid Build Coastguard Worker if (path.isEmpty()) {
396*c8dee2aaSAndroid Build Coastguard Worker return;
397*c8dee2aaSAndroid Build Coastguard Worker }
398*c8dee2aaSAndroid Build Coastguard Worker SkRect clipBounds = SkRect::Make(fDevClipBounds);
399*c8dee2aaSAndroid Build Coastguard Worker path.transform(fViewMatrix);
400*c8dee2aaSAndroid Build Coastguard Worker SkScalar tol = GrPathUtils::kDefaultTolerance;
401*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> vertexBuffer;
402*c8dee2aaSAndroid Build Coastguard Worker int firstVertex;
403*c8dee2aaSAndroid Build Coastguard Worker GrEagerDynamicVertexAllocator allocator(target, &vertexBuffer, &firstVertex);
404*c8dee2aaSAndroid Build Coastguard Worker int vertexCount = GrAATriangulator::PathToAATriangles(path, tol, clipBounds, &allocator);
405*c8dee2aaSAndroid Build Coastguard Worker if (vertexCount == 0) {
406*c8dee2aaSAndroid Build Coastguard Worker return;
407*c8dee2aaSAndroid Build Coastguard Worker }
408*c8dee2aaSAndroid Build Coastguard Worker fMesh = CreateMesh(target, std::move(vertexBuffer), firstVertex, vertexCount);
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker
programInfo()411*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* programInfo() override { return fProgramInfo; }
412*c8dee2aaSAndroid Build Coastguard Worker
onCreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)413*c8dee2aaSAndroid Build Coastguard Worker void onCreateProgramInfo(const GrCaps* caps,
414*c8dee2aaSAndroid Build Coastguard Worker SkArenaAlloc* arena,
415*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
416*c8dee2aaSAndroid Build Coastguard Worker bool usesMSAASurface,
417*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip&& appliedClip,
418*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView& dstProxyView,
419*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
420*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) override {
421*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* gp;
422*c8dee2aaSAndroid Build Coastguard Worker {
423*c8dee2aaSAndroid Build Coastguard Worker using namespace GrDefaultGeoProcFactory;
424*c8dee2aaSAndroid Build Coastguard Worker
425*c8dee2aaSAndroid Build Coastguard Worker Color color(fColor);
426*c8dee2aaSAndroid Build Coastguard Worker LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
427*c8dee2aaSAndroid Build Coastguard Worker ? LocalCoords::kUsePosition_Type
428*c8dee2aaSAndroid Build Coastguard Worker : LocalCoords::kUnused_Type;
429*c8dee2aaSAndroid Build Coastguard Worker Coverage::Type coverageType;
430*c8dee2aaSAndroid Build Coastguard Worker if (fAntiAlias) {
431*c8dee2aaSAndroid Build Coastguard Worker if (fHelper.compatibleWithCoverageAsAlpha()) {
432*c8dee2aaSAndroid Build Coastguard Worker coverageType = Coverage::kAttributeTweakAlpha_Type;
433*c8dee2aaSAndroid Build Coastguard Worker } else {
434*c8dee2aaSAndroid Build Coastguard Worker coverageType = Coverage::kAttribute_Type;
435*c8dee2aaSAndroid Build Coastguard Worker }
436*c8dee2aaSAndroid Build Coastguard Worker } else {
437*c8dee2aaSAndroid Build Coastguard Worker coverageType = Coverage::kSolid_Type;
438*c8dee2aaSAndroid Build Coastguard Worker }
439*c8dee2aaSAndroid Build Coastguard Worker if (fAntiAlias) {
440*c8dee2aaSAndroid Build Coastguard Worker gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(arena, color, coverageType,
441*c8dee2aaSAndroid Build Coastguard Worker localCoordsType, fViewMatrix);
442*c8dee2aaSAndroid Build Coastguard Worker } else {
443*c8dee2aaSAndroid Build Coastguard Worker gp = GrDefaultGeoProcFactory::Make(arena, color, coverageType, localCoordsType,
444*c8dee2aaSAndroid Build Coastguard Worker fViewMatrix);
445*c8dee2aaSAndroid Build Coastguard Worker }
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker if (!gp) {
448*c8dee2aaSAndroid Build Coastguard Worker return;
449*c8dee2aaSAndroid Build Coastguard Worker }
450*c8dee2aaSAndroid Build Coastguard Worker
451*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
452*c8dee2aaSAndroid Build Coastguard Worker auto vertexStride = sizeof(SkPoint);
453*c8dee2aaSAndroid Build Coastguard Worker if (fAntiAlias) {
454*c8dee2aaSAndroid Build Coastguard Worker vertexStride += sizeof(float);
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(vertexStride == gp->vertexStride());
457*c8dee2aaSAndroid Build Coastguard Worker #endif
458*c8dee2aaSAndroid Build Coastguard Worker
459*c8dee2aaSAndroid Build Coastguard Worker GrPrimitiveType primitiveType = TRIANGULATOR_WIREFRAME ? GrPrimitiveType::kLines
460*c8dee2aaSAndroid Build Coastguard Worker : GrPrimitiveType::kTriangles;
461*c8dee2aaSAndroid Build Coastguard Worker
462*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo = fHelper.createProgramInfoWithStencil(caps, arena, writeView,
463*c8dee2aaSAndroid Build Coastguard Worker usesMSAASurface,
464*c8dee2aaSAndroid Build Coastguard Worker std::move(appliedClip), dstProxyView,
465*c8dee2aaSAndroid Build Coastguard Worker gp, primitiveType,
466*c8dee2aaSAndroid Build Coastguard Worker renderPassXferBarriers, colorLoadOp);
467*c8dee2aaSAndroid Build Coastguard Worker }
468*c8dee2aaSAndroid Build Coastguard Worker
onPrePrepareDraws(GrRecordingContext * rContext,const GrSurfaceProxyView & writeView,GrAppliedClip * clip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)469*c8dee2aaSAndroid Build Coastguard Worker void onPrePrepareDraws(GrRecordingContext* rContext,
470*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
471*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip* clip,
472*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView& dstProxyView,
473*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
474*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) override {
475*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia.gpu", TRACE_FUNC);
476*c8dee2aaSAndroid Build Coastguard Worker
477*c8dee2aaSAndroid Build Coastguard Worker INHERITED::onPrePrepareDraws(rContext, writeView, clip, dstProxyView,
478*c8dee2aaSAndroid Build Coastguard Worker renderPassXferBarriers, colorLoadOp);
479*c8dee2aaSAndroid Build Coastguard Worker
480*c8dee2aaSAndroid Build Coastguard Worker if (fAntiAlias) {
481*c8dee2aaSAndroid Build Coastguard Worker // TODO: pull the triangulation work forward to the recording thread for the AA case
482*c8dee2aaSAndroid Build Coastguard Worker // too.
483*c8dee2aaSAndroid Build Coastguard Worker return;
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker
486*c8dee2aaSAndroid Build Coastguard Worker auto threadSafeViewCache = rContext->priv().threadSafeCache();
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
489*c8dee2aaSAndroid Build Coastguard Worker CreateKey(&key, fShape, fDevClipBounds);
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker SkScalar tol = GrPathUtils::scaleToleranceToSrc(GrPathUtils::kDefaultTolerance,
492*c8dee2aaSAndroid Build Coastguard Worker fViewMatrix, fShape.bounds());
493*c8dee2aaSAndroid Build Coastguard Worker
494*c8dee2aaSAndroid Build Coastguard Worker auto [cachedVerts, data] = threadSafeViewCache->findVertsWithData(key);
495*c8dee2aaSAndroid Build Coastguard Worker if (cachedVerts && cache_match(data.get(), tol)) {
496*c8dee2aaSAndroid Build Coastguard Worker fVertexData = std::move(cachedVerts);
497*c8dee2aaSAndroid Build Coastguard Worker return;
498*c8dee2aaSAndroid Build Coastguard Worker }
499*c8dee2aaSAndroid Build Coastguard Worker
500*c8dee2aaSAndroid Build Coastguard Worker GrCpuVertexAllocator allocator;
501*c8dee2aaSAndroid Build Coastguard Worker
502*c8dee2aaSAndroid Build Coastguard Worker bool isLinear;
503*c8dee2aaSAndroid Build Coastguard Worker int vertexCount = Triangulate(&allocator, fViewMatrix, fShape, fDevClipBounds, tol,
504*c8dee2aaSAndroid Build Coastguard Worker &isLinear);
505*c8dee2aaSAndroid Build Coastguard Worker if (vertexCount == 0) {
506*c8dee2aaSAndroid Build Coastguard Worker return;
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker
509*c8dee2aaSAndroid Build Coastguard Worker fVertexData = allocator.detachVertexData();
510*c8dee2aaSAndroid Build Coastguard Worker
511*c8dee2aaSAndroid Build Coastguard Worker key.setCustomData(create_data(vertexCount, isLinear, tol));
512*c8dee2aaSAndroid Build Coastguard Worker
513*c8dee2aaSAndroid Build Coastguard Worker // If some other thread created and cached its own triangulation, the 'is_newer_better'
514*c8dee2aaSAndroid Build Coastguard Worker // predicate will replace the version in the cache if 'fVertexData' is a more accurate
515*c8dee2aaSAndroid Build Coastguard Worker // triangulation. This will leave some other recording threads using a poorer triangulation
516*c8dee2aaSAndroid Build Coastguard Worker // but will result in a version with greater applicability being in the cache.
517*c8dee2aaSAndroid Build Coastguard Worker auto [tmpV, tmpD] = threadSafeViewCache->addVertsWithData(key, fVertexData,
518*c8dee2aaSAndroid Build Coastguard Worker is_newer_better);
519*c8dee2aaSAndroid Build Coastguard Worker if (tmpV != fVertexData) {
520*c8dee2aaSAndroid Build Coastguard Worker // Someone beat us to creating the triangulation (and it is better than ours) so
521*c8dee2aaSAndroid Build Coastguard Worker // just go ahead and use it.
522*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(cache_match(tmpD.get(), tol));
523*c8dee2aaSAndroid Build Coastguard Worker fVertexData = std::move(tmpV);
524*c8dee2aaSAndroid Build Coastguard Worker } else {
525*c8dee2aaSAndroid Build Coastguard Worker // This isn't perfect. The current triangulation is in the cache but it may have
526*c8dee2aaSAndroid Build Coastguard Worker // replaced a pre-existing one. A duplicated listener is unlikely and not that
527*c8dee2aaSAndroid Build Coastguard Worker // expensive so we just roll with it.
528*c8dee2aaSAndroid Build Coastguard Worker fShape.addGenIDChangeListener(
529*c8dee2aaSAndroid Build Coastguard Worker sk_make_sp<UniqueKeyInvalidator>(key, rContext->priv().contextID()));
530*c8dee2aaSAndroid Build Coastguard Worker }
531*c8dee2aaSAndroid Build Coastguard Worker }
532*c8dee2aaSAndroid Build Coastguard Worker
onPrepareDraws(GrMeshDrawTarget * target)533*c8dee2aaSAndroid Build Coastguard Worker void onPrepareDraws(GrMeshDrawTarget* target) override {
534*c8dee2aaSAndroid Build Coastguard Worker if (fAntiAlias) {
535*c8dee2aaSAndroid Build Coastguard Worker this->createAAMesh(target);
536*c8dee2aaSAndroid Build Coastguard Worker } else {
537*c8dee2aaSAndroid Build Coastguard Worker this->createNonAAMesh(target);
538*c8dee2aaSAndroid Build Coastguard Worker }
539*c8dee2aaSAndroid Build Coastguard Worker }
540*c8dee2aaSAndroid Build Coastguard Worker
CreateMesh(GrMeshDrawTarget * target,sk_sp<const GrBuffer> vb,int firstVertex,int count)541*c8dee2aaSAndroid Build Coastguard Worker static GrSimpleMesh* CreateMesh(GrMeshDrawTarget* target,
542*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> vb,
543*c8dee2aaSAndroid Build Coastguard Worker int firstVertex,
544*c8dee2aaSAndroid Build Coastguard Worker int count) {
545*c8dee2aaSAndroid Build Coastguard Worker auto mesh = target->allocMesh();
546*c8dee2aaSAndroid Build Coastguard Worker mesh->set(std::move(vb), count, firstVertex);
547*c8dee2aaSAndroid Build Coastguard Worker return mesh;
548*c8dee2aaSAndroid Build Coastguard Worker }
549*c8dee2aaSAndroid Build Coastguard Worker
onExecute(GrOpFlushState * flushState,const SkRect & chainBounds)550*c8dee2aaSAndroid Build Coastguard Worker void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
551*c8dee2aaSAndroid Build Coastguard Worker if (!fProgramInfo) {
552*c8dee2aaSAndroid Build Coastguard Worker this->createProgramInfo(flushState);
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker if (!fProgramInfo || !fMesh) {
556*c8dee2aaSAndroid Build Coastguard Worker return;
557*c8dee2aaSAndroid Build Coastguard Worker }
558*c8dee2aaSAndroid Build Coastguard Worker
559*c8dee2aaSAndroid Build Coastguard Worker flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
560*c8dee2aaSAndroid Build Coastguard Worker flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
561*c8dee2aaSAndroid Build Coastguard Worker flushState->drawMesh(*fMesh);
562*c8dee2aaSAndroid Build Coastguard Worker }
563*c8dee2aaSAndroid Build Coastguard Worker
564*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
onDumpInfo() const565*c8dee2aaSAndroid Build Coastguard Worker SkString onDumpInfo() const override {
566*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("Color 0x%08x, aa: %d\n%s",
567*c8dee2aaSAndroid Build Coastguard Worker fColor.toBytes_RGBA(), fAntiAlias, fHelper.dumpInfo().c_str());
568*c8dee2aaSAndroid Build Coastguard Worker }
569*c8dee2aaSAndroid Build Coastguard Worker #endif
570*c8dee2aaSAndroid Build Coastguard Worker
571*c8dee2aaSAndroid Build Coastguard Worker Helper fHelper;
572*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f fColor;
573*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape fShape;
574*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fViewMatrix;
575*c8dee2aaSAndroid Build Coastguard Worker SkIRect fDevClipBounds;
576*c8dee2aaSAndroid Build Coastguard Worker bool fAntiAlias;
577*c8dee2aaSAndroid Build Coastguard Worker
578*c8dee2aaSAndroid Build Coastguard Worker GrSimpleMesh* fMesh = nullptr;
579*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* fProgramInfo = nullptr;
580*c8dee2aaSAndroid Build Coastguard Worker
581*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafeCache::VertexData> fVertexData;
582*c8dee2aaSAndroid Build Coastguard Worker
583*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrMeshDrawOp;
584*c8dee2aaSAndroid Build Coastguard Worker };
585*c8dee2aaSAndroid Build Coastguard Worker
586*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
587*c8dee2aaSAndroid Build Coastguard Worker
588*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
589*c8dee2aaSAndroid Build Coastguard Worker
590*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
591*c8dee2aaSAndroid Build Coastguard Worker
GR_DRAW_OP_TEST_DEFINE(TriangulatingPathOp)592*c8dee2aaSAndroid Build Coastguard Worker GR_DRAW_OP_TEST_DEFINE(TriangulatingPathOp) {
593*c8dee2aaSAndroid Build Coastguard Worker SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
594*c8dee2aaSAndroid Build Coastguard Worker const SkPath& path = GrTest::TestPath(random);
595*c8dee2aaSAndroid Build Coastguard Worker SkIRect devClipBounds = SkIRect::MakeLTRB(
596*c8dee2aaSAndroid Build Coastguard Worker random->nextU(), random->nextU(), random->nextU(), random->nextU());
597*c8dee2aaSAndroid Build Coastguard Worker devClipBounds.sort();
598*c8dee2aaSAndroid Build Coastguard Worker static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
599*c8dee2aaSAndroid Build Coastguard Worker GrAAType aaType;
600*c8dee2aaSAndroid Build Coastguard Worker do {
601*c8dee2aaSAndroid Build Coastguard Worker aaType = kAATypes[random->nextULessThan(std::size(kAATypes))];
602*c8dee2aaSAndroid Build Coastguard Worker } while(GrAAType::kMSAA == aaType && numSamples <= 1);
603*c8dee2aaSAndroid Build Coastguard Worker GrStyle style;
604*c8dee2aaSAndroid Build Coastguard Worker do {
605*c8dee2aaSAndroid Build Coastguard Worker GrTest::TestStyle(random, &style);
606*c8dee2aaSAndroid Build Coastguard Worker } while (!style.isSimpleFill());
607*c8dee2aaSAndroid Build Coastguard Worker GrStyledShape shape(path, style);
608*c8dee2aaSAndroid Build Coastguard Worker return TriangulatingPathOp::Make(context, std::move(paint), shape, viewMatrix, devClipBounds,
609*c8dee2aaSAndroid Build Coastguard Worker aaType, GrGetRandomStencil(random, context));
610*c8dee2aaSAndroid Build Coastguard Worker }
611*c8dee2aaSAndroid Build Coastguard Worker
612*c8dee2aaSAndroid Build Coastguard Worker #endif
613*c8dee2aaSAndroid Build Coastguard Worker
614*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
615*c8dee2aaSAndroid Build Coastguard Worker
616*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::ganesh {
617*c8dee2aaSAndroid Build Coastguard Worker
TriangulatingPathRenderer()618*c8dee2aaSAndroid Build Coastguard Worker TriangulatingPathRenderer::TriangulatingPathRenderer()
619*c8dee2aaSAndroid Build Coastguard Worker : fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
620*c8dee2aaSAndroid Build Coastguard Worker }
621*c8dee2aaSAndroid Build Coastguard Worker
onCanDrawPath(const CanDrawPathArgs & args) const622*c8dee2aaSAndroid Build Coastguard Worker PathRenderer::CanDrawPath TriangulatingPathRenderer::onCanDrawPath(
623*c8dee2aaSAndroid Build Coastguard Worker const CanDrawPathArgs& args) const {
624*c8dee2aaSAndroid Build Coastguard Worker
625*c8dee2aaSAndroid Build Coastguard Worker // Don't use this path renderer with dynamic MSAA. DMSAA tries to not rely on caching.
626*c8dee2aaSAndroid Build Coastguard Worker if (args.fSurfaceProps->flags() & SkSurfaceProps::kDynamicMSAA_Flag) {
627*c8dee2aaSAndroid Build Coastguard Worker return CanDrawPath::kNo;
628*c8dee2aaSAndroid Build Coastguard Worker }
629*c8dee2aaSAndroid Build Coastguard Worker // This path renderer can draw fill styles, and can do screenspace antialiasing via a
630*c8dee2aaSAndroid Build Coastguard Worker // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
631*c8dee2aaSAndroid Build Coastguard Worker // ones to simpler algorithms. We pass on paths that have styles, though they may come back
632*c8dee2aaSAndroid Build Coastguard Worker // around after applying the styling information to the geometry to create a filled path.
633*c8dee2aaSAndroid Build Coastguard Worker if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
634*c8dee2aaSAndroid Build Coastguard Worker return CanDrawPath::kNo;
635*c8dee2aaSAndroid Build Coastguard Worker }
636*c8dee2aaSAndroid Build Coastguard Worker switch (args.fAAType) {
637*c8dee2aaSAndroid Build Coastguard Worker case GrAAType::kNone:
638*c8dee2aaSAndroid Build Coastguard Worker case GrAAType::kMSAA:
639*c8dee2aaSAndroid Build Coastguard Worker // Prefer MSAA, if any antialiasing. In the non-analytic-AA case, We skip paths that
640*c8dee2aaSAndroid Build Coastguard Worker // don't have a key since the real advantage of this path renderer comes from caching
641*c8dee2aaSAndroid Build Coastguard Worker // the tessellated geometry.
642*c8dee2aaSAndroid Build Coastguard Worker if (!args.fShape->hasUnstyledKey()) {
643*c8dee2aaSAndroid Build Coastguard Worker return CanDrawPath::kNo;
644*c8dee2aaSAndroid Build Coastguard Worker }
645*c8dee2aaSAndroid Build Coastguard Worker break;
646*c8dee2aaSAndroid Build Coastguard Worker case GrAAType::kCoverage:
647*c8dee2aaSAndroid Build Coastguard Worker // Use analytic AA if we don't have MSAA. In this case, we do not cache, so we accept
648*c8dee2aaSAndroid Build Coastguard Worker // paths without keys.
649*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
650*c8dee2aaSAndroid Build Coastguard Worker args.fShape->asPath(&path);
651*c8dee2aaSAndroid Build Coastguard Worker if (path.countVerbs() > fMaxVerbCount) {
652*c8dee2aaSAndroid Build Coastguard Worker return CanDrawPath::kNo;
653*c8dee2aaSAndroid Build Coastguard Worker }
654*c8dee2aaSAndroid Build Coastguard Worker break;
655*c8dee2aaSAndroid Build Coastguard Worker }
656*c8dee2aaSAndroid Build Coastguard Worker return CanDrawPath::kYes;
657*c8dee2aaSAndroid Build Coastguard Worker }
658*c8dee2aaSAndroid Build Coastguard Worker
onDrawPath(const DrawPathArgs & args)659*c8dee2aaSAndroid Build Coastguard Worker bool TriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
660*c8dee2aaSAndroid Build Coastguard Worker GR_AUDIT_TRAIL_AUTO_FRAME(args.fContext->priv().auditTrail(),
661*c8dee2aaSAndroid Build Coastguard Worker "GrTriangulatingPathRenderer::onDrawPath");
662*c8dee2aaSAndroid Build Coastguard Worker
663*c8dee2aaSAndroid Build Coastguard Worker GrOp::Owner op = TriangulatingPathOp::Make(
664*c8dee2aaSAndroid Build Coastguard Worker args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
665*c8dee2aaSAndroid Build Coastguard Worker *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
666*c8dee2aaSAndroid Build Coastguard Worker args.fSurfaceDrawContext->addDrawOp(args.fClip, std::move(op));
667*c8dee2aaSAndroid Build Coastguard Worker return true;
668*c8dee2aaSAndroid Build Coastguard Worker }
669*c8dee2aaSAndroid Build Coastguard Worker
670*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::ganesh
671*c8dee2aaSAndroid Build Coastguard Worker
672*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_ENABLE_OPTIMIZE_SIZE
673