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