1d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/*
2d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Copyright 2015 Google Inc.
3d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco *
4d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * Use of this source code is governed by a BSD-style license that can be
5d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco * found in the LICENSE file.
6d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
7d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
8d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrTessellatingPathRenderer.h"
9d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
10976f5f0dc5e907d1ca50685fad117bd15d7fc87brobertphillips#include "GrAuditTrail.h"
11976f5f0dc5e907d1ca50685fad117bd15d7fc87brobertphillips#include "GrClip.h"
12d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrDefaultGeoProcFactory.h"
135ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h"
140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel#include "GrMesh.h"
15742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
16d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "GrPathUtils.h"
1784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco#include "GrResourceCache.h"
1884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco#include "GrResourceProvider.h"
19e9709e831954c3427d5cb839e84221a177bfedebethannicholas#include "GrTessellator.h"
20d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include "SkGeometry.h"
21d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
229530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon#include "GrSimpleMeshDrawOpHelper.h"
23895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h"
2474417824cd988f7d6114858e09720ba00416ce11joshualitt
25d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco#include <stdio.h>
26d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
27d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco/*
28f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco * This path renderer tessellates the path into triangles using GrTessellator, uploads the
29f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco * triangles to a vertex buffer, and renders them with a single draw call. It can do screenspace
30f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco * antialiasing with a one-pixel coverage ramp.
31d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco */
32d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanconamespace {
33d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
34e9709e831954c3427d5cb839e84221a177bfedebethannicholasstruct TessInfo {
35e9709e831954c3427d5cb839e84221a177bfedebethannicholas    SkScalar  fTolerance;
36e9709e831954c3427d5cb839e84221a177bfedebethannicholas    int       fCount;
37fb8243717300309853ff3d881b68feddd9c7b5c9caryclark};
38fb8243717300309853ff3d881b68feddd9c7b5c9caryclark
39e9709e831954c3427d5cb839e84221a177bfedebethannicholas// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
40e9709e831954c3427d5cb839e84221a177bfedebethannicholasclass PathInvalidator : public SkPathRef::GenIDChangeListener {
41e9709e831954c3427d5cb839e84221a177bfedebethannicholaspublic:
42e9709e831954c3427d5cb839e84221a177bfedebethannicholas    explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {}
43e9709e831954c3427d5cb839e84221a177bfedebethannicholasprivate:
44e9709e831954c3427d5cb839e84221a177bfedebethannicholas    GrUniqueKeyInvalidatedMessage fMsg;
45fb8243717300309853ff3d881b68feddd9c7b5c9caryclark
46e9709e831954c3427d5cb839e84221a177bfedebethannicholas    void onChange() override {
47e9709e831954c3427d5cb839e84221a177bfedebethannicholas        SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
48fb8243717300309853ff3d881b68feddd9c7b5c9caryclark    }
4984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco};
5084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
51397536cabe12a9936659870dd220c869789424bacdaltonbool cache_match(GrBuffer* vertexBuffer, SkScalar tol, int* actualCount) {
5284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    if (!vertexBuffer) {
5384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        return false;
5484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
5584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    const SkData* data = vertexBuffer->getUniqueKey().getCustomData();
5684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    SkASSERT(data);
5784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    const TessInfo* info = static_cast<const TessInfo*>(data->data());
5884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) {
5906f989a61e4b0237e338a54d2cc0efd531cf0041senorblanco        *actualCount = info->fCount;
6084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        return true;
6184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
6284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    return false;
6384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco}
6484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
656599efffeef3168dfc68dca99c30454c5c23b859senorblancoclass StaticVertexAllocator : public GrTessellator::VertexAllocator {
666599efffeef3168dfc68dca99c30454c5c23b859senorblancopublic:
67f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    StaticVertexAllocator(size_t stride, GrResourceProvider* resourceProvider, bool canMapVB)
68f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco      : VertexAllocator(stride)
69f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco      , fResourceProvider(resourceProvider)
706599efffeef3168dfc68dca99c30454c5c23b859senorblanco      , fCanMapVB(canMapVB)
716599efffeef3168dfc68dca99c30454c5c23b859senorblanco      , fVertices(nullptr) {
726599efffeef3168dfc68dca99c30454c5c23b859senorblanco    }
73f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void* lock(int vertexCount) override {
74f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        size_t size = vertexCount * stride();
75397536cabe12a9936659870dd220c869789424bacdalton        fVertexBuffer.reset(fResourceProvider->createBuffer(
76e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton            size, kVertex_GrBufferType, kStatic_GrAccessPattern, 0));
776599efffeef3168dfc68dca99c30454c5c23b859senorblanco        if (!fVertexBuffer.get()) {
786599efffeef3168dfc68dca99c30454c5c23b859senorblanco            return nullptr;
796599efffeef3168dfc68dca99c30454c5c23b859senorblanco        }
806599efffeef3168dfc68dca99c30454c5c23b859senorblanco        if (fCanMapVB) {
81f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            fVertices = fVertexBuffer->map();
826599efffeef3168dfc68dca99c30454c5c23b859senorblanco        } else {
83f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            fVertices = sk_malloc_throw(vertexCount * stride());
846599efffeef3168dfc68dca99c30454c5c23b859senorblanco        }
856599efffeef3168dfc68dca99c30454c5c23b859senorblanco        return fVertices;
866599efffeef3168dfc68dca99c30454c5c23b859senorblanco    }
876599efffeef3168dfc68dca99c30454c5c23b859senorblanco    void unlock(int actualCount) override {
886599efffeef3168dfc68dca99c30454c5c23b859senorblanco        if (fCanMapVB) {
896599efffeef3168dfc68dca99c30454c5c23b859senorblanco            fVertexBuffer->unmap();
906599efffeef3168dfc68dca99c30454c5c23b859senorblanco        } else {
91f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            fVertexBuffer->updateData(fVertices, actualCount * stride());
92f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            sk_free(fVertices);
936599efffeef3168dfc68dca99c30454c5c23b859senorblanco        }
946599efffeef3168dfc68dca99c30454c5c23b859senorblanco        fVertices = nullptr;
956599efffeef3168dfc68dca99c30454c5c23b859senorblanco    }
96397536cabe12a9936659870dd220c869789424bacdalton    GrBuffer* vertexBuffer() { return fVertexBuffer.get(); }
976599efffeef3168dfc68dca99c30454c5c23b859senorblancoprivate:
98144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary    sk_sp<GrBuffer> fVertexBuffer;
996599efffeef3168dfc68dca99c30454c5c23b859senorblanco    GrResourceProvider* fResourceProvider;
1006599efffeef3168dfc68dca99c30454c5c23b859senorblanco    bool fCanMapVB;
101f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void* fVertices;
102f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco};
103f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco
104f57372daf0562a187c24d427366ac6d0cb980c9bsenorblancoclass DynamicVertexAllocator : public GrTessellator::VertexAllocator {
105f57372daf0562a187c24d427366ac6d0cb980c9bsenorblancopublic:
106e5b399ee69332e0d68a660d6695d1182a4cb16b1Brian Salomon    DynamicVertexAllocator(size_t stride, GrMeshDrawOp::Target* target)
107d3ccb0a37f0e62c84fdcd6a77b7b15476b04db7aBrian Salomon            : VertexAllocator(stride)
108d3ccb0a37f0e62c84fdcd6a77b7b15476b04db7aBrian Salomon            , fTarget(target)
109d3ccb0a37f0e62c84fdcd6a77b7b15476b04db7aBrian Salomon            , fVertexBuffer(nullptr)
110d3ccb0a37f0e62c84fdcd6a77b7b15476b04db7aBrian Salomon            , fVertices(nullptr) {}
111f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void* lock(int vertexCount) override {
112f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        fVertexCount = vertexCount;
113f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        fVertices = fTarget->makeVertexSpace(stride(), vertexCount, &fVertexBuffer, &fFirstVertex);
114f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        return fVertices;
115f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
116f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void unlock(int actualCount) override {
117f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        fTarget->putBackVertices(fVertexCount - actualCount, stride());
118f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        fVertices = nullptr;
119f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
120f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    const GrBuffer* vertexBuffer() const { return fVertexBuffer; }
121f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    int firstVertex() const { return fFirstVertex; }
122f57372daf0562a187c24d427366ac6d0cb980c9bsenorblancoprivate:
123e5b399ee69332e0d68a660d6695d1182a4cb16b1Brian Salomon    GrMeshDrawOp::Target* fTarget;
124f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    const GrBuffer* fVertexBuffer;
125f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    int fVertexCount;
126f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    int fFirstVertex;
127f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void* fVertices;
1286599efffeef3168dfc68dca99c30454c5c23b859senorblanco};
1296599efffeef3168dfc68dca99c30454c5c23b859senorblanco
130e9709e831954c3427d5cb839e84221a177bfedebethannicholas}  // namespace
131d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
132d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblancoGrTessellatingPathRenderer::GrTessellatingPathRenderer() {
133d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
134d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1350aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
136f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // This path renderer can draw fill styles, and can do screenspace antialiasing via a
137f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // one-pixel coverage ramp. It can do convex and concave paths, but we'll leave the convex
138f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // ones to simpler algorithms. We pass on paths that have styles, though they may come back
139f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // around after applying the styling information to the geometry to create a filled path. In
140f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // the non-AA case, We skip paths thta don't have a key since the real advantage of this path
141f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // renderer comes from caching the tessellated geometry. In the AA case, we do not cache, so we
142f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    // accept paths without keys.
143f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
144f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        return false;
145f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
1460e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon    if (GrAAType::kCoverage == args.fAAType) {
147021f927e4cb8293a56923b763682217067486878Stephan White        SkPath path;
148021f927e4cb8293a56923b763682217067486878Stephan White        args.fShape->asPath(&path);
149021f927e4cb8293a56923b763682217067486878Stephan White        if (path.countVerbs() > 10) {
150021f927e4cb8293a56923b763682217067486878Stephan White            return false;
151021f927e4cb8293a56923b763682217067486878Stephan White        }
152f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    } else if (!args.fShape->hasUnstyledKey()) {
153f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        return false;
154f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
155f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    return true;
156d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
157d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco
1589530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomonnamespace {
1599530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon
1609530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomonclass TessellatingPathOp final : public GrMeshDrawOp {
1619530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomonprivate:
1629530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    using Helper = GrSimpleMeshDrawOpHelperWithStencil;
1639530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon
1649ba3972ed93321ee606e2974e00a926cd871ddccsenorblancopublic:
16525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
1669ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
1679530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
1689530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                          const GrShape& shape,
1699530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                          const SkMatrix& viewMatrix,
1709530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                          SkIRect devClipBounds,
1719530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                          GrAAType aaType,
1729530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                          const GrUserStencilSettings* stencilSettings) {
1739530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        return Helper::FactoryHelper<TessellatingPathOp>(std::move(paint), shape, viewMatrix,
1749530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                         devClipBounds, aaType, stencilSettings);
1759ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
1769ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
177a6aa590efc8201747c069f9da2285250957df01bBrian Salomon    const char* name() const override { return "TessellatingPathOp"; }
1789ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
1797c3e7180948766321c51d165737555e78910de51Brian Salomon    SkString dumpInfo() const override {
1807c3e7180948766321c51d165737555e78910de51Brian Salomon        SkString string;
1817c3e7180948766321c51d165737555e78910de51Brian Salomon        string.appendf("Color 0x%08x, aa: %d\n", fColor, fAntiAlias);
1829530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        string += fHelper.dumpInfo();
1839530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        string += INHERITED::dumpInfo();
1847c3e7180948766321c51d165737555e78910de51Brian Salomon        return string;
1857c3e7180948766321c51d165737555e78910de51Brian Salomon    }
1867c3e7180948766321c51d165737555e78910de51Brian Salomon
1879530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    TessellatingPathOp(Helper::MakeArgs helperArgs,
1889530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       GrColor color,
1899530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       const GrShape& shape,
1909530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       const SkMatrix& viewMatrix,
1919530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       const SkIRect& devClipBounds,
1929530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       GrAAType aaType,
1939530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                       const GrUserStencilSettings* stencilSettings)
1949530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            : INHERITED(ClassID())
1959530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fHelper(helperArgs, aaType, stencilSettings)
1969530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fColor(color)
1979530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fShape(shape)
1989530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fViewMatrix(viewMatrix)
1999530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fDevClipBounds(devClipBounds)
2009530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            , fAntiAlias(GrAAType::kCoverage == aaType) {
2019530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        SkRect devBounds;
2029530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        viewMatrix.mapRect(&devBounds, shape.bounds());
2039530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        if (shape.inverseFilled()) {
2049530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            // Because the clip bounds are used to add a contour for inverse fills, they must also
2059530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            // include the path bounds.
2069530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            devBounds.join(SkRect::Make(fDevClipBounds));
2079530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        }
2089530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
2099ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
2109ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
2119530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
2129530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon
2139530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
2149530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        GrProcessorAnalysisCoverage coverage = fAntiAlias
2159530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                       ? GrProcessorAnalysisCoverage::kSingleChannel
2169530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                       : GrProcessorAnalysisCoverage::kNone;
2179530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        return fHelper.xpRequiresDstTexture(caps, clip, coverage, &fColor);
2189ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
2199ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
2209530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomonprivate:
221f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    SkPath getPath() const {
222f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkASSERT(!fShape.style().applies());
223682580fb204b72925a48d1d6fe8c9c30fa53bb67senorblanco        SkPath path;
224682580fb204b72925a48d1d6fe8c9c30fa53bb67senorblanco        fShape.asPath(&path);
225f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        return path;
226f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
227f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco
228f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void draw(Target* target, const GrGeometryProcessor* gp) const {
229f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkASSERT(!fAntiAlias);
230f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        GrResourceProvider* rp = target->resourceProvider();
231f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        bool inverseFill = fShape.inverseFilled();
23284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        // construct a cache key from the path's genID and the view matrix
23384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
23484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        GrUniqueKey key;
235f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(uint32_t);
236ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        int shapeKeyDataCnt = fShape.unstyledKeySize();
237ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        SkASSERT(shapeKeyDataCnt >= 0);
238ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt);
239ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        fShape.writeUnstyledKey(&builder[0]);
240ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        // For inverse fills, the tessellation is dependent on clip bounds.
241ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        if (inverseFill) {
242f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            memcpy(&builder[shapeKeyDataCnt], &fDevClipBounds, sizeof(fDevClipBounds));
2436599efffeef3168dfc68dca99c30454c5c23b859senorblanco        } else {
244f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            memset(&builder[shapeKeyDataCnt], 0, sizeof(fDevClipBounds));
245ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        }
246ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        builder.finish();
247144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary        sk_sp<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key));
248ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        int actualCount;
249f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkScalar tol = GrPathUtils::kDefaultTolerance;
250f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds());
251ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
252ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon            this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount);
253ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon            return;
2546599efffeef3168dfc68dca99c30454c5c23b859senorblanco        }
255ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon
256f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkRect clipBounds = SkRect::Make(fDevClipBounds);
257f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco
258f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkMatrix vmi;
259f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        if (!fViewMatrix.invert(&vmi)) {
260f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            return;
261f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        }
262f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        vmi.mapRect(&clipBounds);
2636599efffeef3168dfc68dca99c30454c5c23b859senorblanco        bool isLinear;
2646599efffeef3168dfc68dca99c30454c5c23b859senorblanco        bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
265f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        StaticVertexAllocator allocator(gp->getVertexStride(), rp, canMapVB);
266f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, &allocator,
267f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco                                                   false, GrColor(), false, &isLinear);
2686599efffeef3168dfc68dca99c30454c5c23b859senorblanco        if (count == 0) {
26984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            return;
27084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        }
271af1e21e7ebb155d2505da0eb974c672953dfefefsenorblanco        this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count);
272ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        TessInfo info;
273ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        info.fTolerance = isLinear ? 0 : tol;
274ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        info.fCount = count;
27538d909ec2875f79952de08f36adfaac5680d2c53bungeman        key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info)));
276ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon        rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
2776599efffeef3168dfc68dca99c30454c5c23b859senorblanco    }
27884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
279f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    void drawAA(Target* target, const GrGeometryProcessor* gp) const {
280f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkASSERT(fAntiAlias);
281f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkPath path = getPath();
282f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        if (path.isEmpty()) {
283f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            return;
284f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        }
285f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkRect clipBounds = SkRect::Make(fDevClipBounds);
286f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        path.transform(fViewMatrix);
287f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        SkScalar tol = GrPathUtils::kDefaultTolerance;
288f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        bool isLinear;
289f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        DynamicVertexAllocator allocator(gp->getVertexStride(), target);
2909530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        int count =
2919530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                GrTessellator::PathToTriangles(path, tol, clipBounds, &allocator, true, fColor,
2929530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                               fHelper.compatibleWithAlphaAsCoverage(), &isLinear);
293f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        if (count == 0) {
294f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            return;
295f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        }
296f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        drawVertices(target, gp, allocator.vertexBuffer(), allocator.firstVertex(), count);
297f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    }
298f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco
2996599efffeef3168dfc68dca99c30454c5c23b859senorblanco    void onPrepareDraws(Target* target) const override {
30006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        sk_sp<GrGeometryProcessor> gp;
30184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        {
30284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            using namespace GrDefaultGeoProcFactory;
30384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
30484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            Color color(fColor);
3059530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon            LocalCoords::Type localCoordsType = fHelper.usesLocalCoords()
3068c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                        ? LocalCoords::kUsePosition_Type
3078c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                        : LocalCoords::kUnused_Type;
30884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            Coverage::Type coverageType;
309f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            if (fAntiAlias) {
3103de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon                color = Color(Color::kPremulGrColorAttribute_Type);
3119530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                if (fHelper.compatibleWithAlphaAsCoverage()) {
312f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco                    coverageType = Coverage::kSolid_Type;
313f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco                } else {
314f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco                    coverageType = Coverage::kAttribute_Type;
315f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco                }
31684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            } else {
3178c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                coverageType = Coverage::kSolid_Type;
31884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco            }
319f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            if (fAntiAlias) {
3208c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(color, coverageType,
3218c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                                 localCoordsType, fViewMatrix);
322f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            } else {
3238c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                gp = GrDefaultGeoProcFactory::Make(color, coverageType, localCoordsType,
3248c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                   fViewMatrix);
325f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            }
326f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        }
327cc70083fbf76fd86b901fffdcce40d0f53787fc8Stephen White        if (!gp.get()) {
328cc70083fbf76fd86b901fffdcce40d0f53787fc8Stephen White            return;
329cc70083fbf76fd86b901fffdcce40d0f53787fc8Stephen White        }
330f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        if (fAntiAlias) {
331f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            this->drawAA(target, gp.get());
332f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        } else {
333f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco            this->draw(target, gp.get());
33484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        }
3356599efffeef3168dfc68dca99c30454c5c23b859senorblanco    }
33684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
337397536cabe12a9936659870dd220c869789424bacdalton    void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb,
3386599efffeef3168dfc68dca99c30454c5c23b859senorblanco                      int firstVertex, int count) const {
3393809bab7ed344ad140346c38e149dabf10bd525fChris Dalton        GrMesh mesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines : GrPrimitiveType::kTriangles);
3401d6163577c8a4f1372208e2c9e03b1a69906d385Chris Dalton        mesh.setNonIndexedNonInstanced(count);
341114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton        mesh.setVertexData(vb, firstVertex);
3429530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        target->draw(gp, fHelper.makePipeline(target), mesh);
3439ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco    }
3449ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
34525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
3469ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
3479530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    Helper fHelper;
34891d844de47bdc1c3f807c85293e46943dcfc712dbsalomon    GrColor                 fColor;
349ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon    GrShape                 fShape;
35091d844de47bdc1c3f807c85293e46943dcfc712dbsalomon    SkMatrix                fViewMatrix;
351f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    SkIRect                 fDevClipBounds;
352f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    bool                    fAntiAlias;
3531b55a963a2374a14bb82eb887bb99ee91680f0ebreed
3549530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    typedef GrMeshDrawOp INHERITED;
3559ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco};
3569ba3972ed93321ee606e2974e00a926cd871ddccsenorblanco
3579530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon}  // anonymous namespace
3589530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon
3590aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
3601105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
361de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt                              "GrTessellatingPathRenderer::onDrawPath");
362d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    SkIRect clipBoundsI;
363784b7bf493c37236e3fe571aed6105939a9bc0c3Robert Phillips    args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
364784b7bf493c37236e3fe571aed6105939a9bc0c3Robert Phillips                                      args.fRenderTargetContext->height(),
365976f5f0dc5e907d1ca50685fad117bd15d7fc87brobertphillips                                      &clipBoundsI);
3669530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    std::unique_ptr<GrDrawOp> op = TessellatingPathOp::Make(std::move(args.fPaint),
3679530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                            *args.fShape,
3689530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                            *args.fViewMatrix,
3699530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                            clipBoundsI,
3709530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                            args.fAAType,
3719530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                                            args.fUserStencilSettings);
3729530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
373d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco    return true;
374d6ed19cc751463285491a538bc7bf154cc7e6d8csenorblanco}
3752fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
3762fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt///////////////////////////////////////////////////////////////////////////////////////////////////
3772fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
3786f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS
3792fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
3809530f7ebf529acce1d6e99fa40032bbf13826a03Brian SalomonGR_DRAW_OP_TEST_DEFINE(TesselatingPathOp) {
3812fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
3822fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt    SkPath path = GrTest::TestPath(random);
383d3030acc2cd46fe5310da0521ce7e85caf1619f6bsalomon    SkIRect devClipBounds = SkIRect::MakeLTRB(
384f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco        random->nextU(), random->nextU(), random->nextU(), random->nextU());
385d3030acc2cd46fe5310da0521ce7e85caf1619f6bsalomon    devClipBounds.sort();
3869530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    static constexpr GrAAType kAATypes[] = {GrAAType::kNone, GrAAType::kMSAA, GrAAType::kCoverage};
3879530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    GrAAType aaType;
3889530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    do {
3899530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon        aaType = kAATypes[random->nextULessThan(SK_ARRAY_COUNT(kAATypes))];
3909530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    } while(GrAAType::kMSAA == aaType && GrFSAAType::kUnifiedMSAA != fsaaType);
3916663acff010ce752e4bf778da81fa97448c9db31bsalomon    GrStyle style;
3926663acff010ce752e4bf778da81fa97448c9db31bsalomon    do {
3936663acff010ce752e4bf778da81fa97448c9db31bsalomon        GrTest::TestStyle(random, &style);
394f57372daf0562a187c24d427366ac6d0cb980c9bsenorblanco    } while (!style.isSimpleFill());
395ee43241d72148545e4e3b75aa4338c491b39cc0cbsalomon    GrShape shape(path, style);
3969530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon    return TessellatingPathOp::Make(std::move(paint), shape, viewMatrix, devClipBounds, aaType,
3979530f7ebf529acce1d6e99fa40032bbf13826a03Brian Salomon                                    GrGetRandomStencil(random, context));
3982fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt}
3992fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt
4002fbd4068bde6a9fb50341c0bdfbb8bf18b70d015joshualitt#endif
401