GrAALinearizingConvexPathRenderer.cpp revision 91326c34ee1f1531d62caa153746821b58e6e55d
11a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/*
21a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Copyright 2015 Google Inc.
31a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *
41a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Use of this source code is governed by a BSD-style license that can be
51a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * found in the LICENSE file.
61a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas */
71a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
81a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAALinearizingConvexPathRenderer.h"
91a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAAConvexTessellator.h"
101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrContext.h"
111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrDefaultGeoProcFactory.h"
125ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h"
131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrGeometryProcessor.h"
14742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h"
16dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrProcessor.h"
176663acff010ce752e4bf778da81fa97448c9db31bsalomon#include "GrStyle.h"
181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h"
19dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "SkPathPriv.h"
201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h"
211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h"
22e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h"
23895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h"
24b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon#include "ops/GrSimpleMeshDrawOpHelper.h"
251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
26bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const int DEFAULT_BUFFER_SIZE = 100;
27bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For
29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// the time being, we simply drop back to software rendering above this stroke width.
30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kMaxStrokeWidth = 20.0;
311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////
361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
370aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
380e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon    if (GrAAType::kCoverage != args.fAAType) {
39bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
40bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
418acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (!args.fShape->knownToBeConvex()) {
42bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
43bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
448acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->style().pathEffect()) {
45bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
46bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
478acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->inverseFilled()) {
486663acff010ce752e4bf778da81fa97448c9db31bsalomon        return false;
496663acff010ce752e4bf778da81fa97448c9db31bsalomon    }
50a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman    if (args.fShape->bounds().width() <= 0 && args.fShape->bounds().height() <= 0) {
51a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman        // Stroked zero length lines should draw, but this PR doesn't handle that case
52a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman        return false;
53a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman    }
548acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    const SkStrokeRec& stroke = args.fShape->style().strokeRec();
558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
58fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        if (!args.fViewMatrix->isSimilarity()) {
59fea7763140ba74b78f2c30028452e250140b6f21ethannicholas            return false;
60fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        }
616663acff010ce752e4bf778da81fa97448c9db31bsalomon        SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            return false;
648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        return strokeWidth <= kMaxStrokeWidth &&
668acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon               args.fShape->knownToBeClosed() &&
676663acff010ce752e4bf778da81fa97448c9db31bsalomon               stroke.getJoin() != SkPaint::Join::kRound_Join;
68bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
696663acff010ce752e4bf778da81fa97448c9db31bsalomon    return stroke.getStyle() == SkStrokeRec::kFill_Style;
701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator
731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess,
741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          void* vertices,
751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          size_t vertexStride,
761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          GrColor color,
771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t firstIndex,
781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t* idxs,
791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          bool tweakAlphaForCoverage) {
801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    intptr_t verts = reinterpret_cast<intptr_t>(vertices);
811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    // Make 'verts' point to the colors
871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    verts += sizeof(SkPoint);
881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (tweakAlphaForCoverage) {
90bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
91bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        } else {
951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
96002c2ce66be69d41632c9603ce62c50f04156518mtklein            *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
97bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    tess.coverage(i);
981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numIndices(); ++i) {
1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        idxs[i] = tess.index(i) + firstIndex;
1031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
10660fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomonstatic sk_sp<GrGeometryProcessor> create_lines_only_gp(bool tweakAlphaForCoverage,
10760fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon                                                       const SkMatrix& viewMatrix,
10860fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon                                                       bool usesLocalCoords) {
109df0c55785033c191d2d509c22662861588e4acd8joshualitt    using namespace GrDefaultGeoProcFactory;
110df0c55785033c191d2d509c22662861588e4acd8joshualitt
111df0c55785033c191d2d509c22662861588e4acd8joshualitt    Coverage::Type coverageType;
1128c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    if (tweakAlphaForCoverage) {
113df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kSolid_Type;
114df0c55785033c191d2d509c22662861588e4acd8joshualitt    } else {
115df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kAttribute_Type;
1161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1178c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    LocalCoords::Type localCoordsType =
1188c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
1193de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
1203de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon                              viewMatrix);
1211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
123b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonnamespace {
1241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
125b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp {
126b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate:
127b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    using Helper = GrSimpleMeshDrawOpHelperWithStencil;
1287c3e7180948766321c51d165737555e78910de51Brian Salomon
129b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonpublic:
130b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    DEFINE_OP_CLASS_ID
131b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint,
132b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          const SkMatrix& viewMatrix,
133b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          const SkPath& path,
134b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          SkScalar strokeWidth,
135b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          SkStrokeRec::Style style,
136b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          SkPaint::Join join,
137b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          SkScalar miterLimit,
138b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          const GrUserStencilSettings* stencilSettings) {
139b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        return Helper::FactoryHelper<AAFlatteningConvexPathOp>(std::move(paint), viewMatrix, path,
140b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                                               strokeWidth, style, join, miterLimit,
141b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                                               stencilSettings);
1427c3e7180948766321c51d165737555e78910de51Brian Salomon    }
1431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
144b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    AAFlatteningConvexPathOp(const Helper::MakeArgs& helperArgs,
145b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                             GrColor color,
146780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkMatrix& viewMatrix,
147780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkPath& path,
148780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkScalar strokeWidth,
149780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkStrokeRec::Style style,
150780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkPaint::Join join,
151b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                             SkScalar miterLimit,
152b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                             const GrUserStencilSettings* stencilSettings)
153b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon            : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        fPaths.emplace_back(
155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit});
156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        // compute bounds
158780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkRect bounds = path.getBounds();
159780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkScalar w = strokeWidth;
160780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        if (w > 0) {
161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            w /= 2;
162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            // If the half stroke width is < 1 then we effectively fallback to bevel joins.
163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            if (SkPaint::kMiter_Join == join && w > 1.f) {
164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                w *= miterLimit;
165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            }
166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            bounds.outset(w, w);
167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        }
168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    }
170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
171b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    const char* name() const override { return "AAFlatteningConvexPathOp"; }
172b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon
173b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    SkString dumpInfo() const override {
174b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        SkString string;
175b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        for (const auto& path : fPaths) {
176b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon            string.appendf(
177b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                    "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, "
178b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                    "MiterLimit: %.2f\n",
179b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                    path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit);
180b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        }
181b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        string += fHelper.dumpInfo();
182b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        string += INHERITED::dumpInfo();
183b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        return string;
18492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    }
18592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon
186b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
187b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon
188b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
189b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
190b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                            &fPaths.back().fColor);
1911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
193b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate:
194b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp,
195b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon              const GrPipeline* pipeline, int vertexCount, size_t vertexStride, void* vertices,
196b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon              int indexCount, uint16_t* indices) const {
1971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (vertexCount == 0 || indexCount == 0) {
1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
200ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton        const GrBuffer* vertexBuffer;
2013809bab7ed344ad140346c38e149dabf10bd525fChris Dalton        GrMesh mesh(GrPrimitiveType::kTriangles);
202bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton        int firstVertex;
203002c2ce66be69d41632c9603ce62c50f04156518mtklein        void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
204bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton                                              &firstVertex);
2051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!verts) {
2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate vertices\n");
2071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(verts, vertices, vertexCount * vertexStride);
2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
211397536cabe12a9936659870dd220c869789424bacdalton        const GrBuffer* indexBuffer;
212bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton        int firstIndex;
213bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton        uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!idxs) {
2151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate indices\n");
2161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(idxs, indices, indexCount * sizeof(uint16_t));
219114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton        mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1);
220114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton        mesh.setVertexData(vertexBuffer, firstVertex);
221b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        target->draw(gp, pipeline, mesh);
2221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
223002c2ce66be69d41632c9603ce62c50f04156518mtklein
22491326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon    void onPrepareDraws(Target* target) override {
225b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        const GrPipeline* pipeline = fHelper.makePipeline(target);
2261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
227df0c55785033c191d2d509c22662861588e4acd8joshualitt        // Setup GrGeometryProcessor
228b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(fHelper.compatibleWithAlphaAsCoverage(),
229b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                                           this->viewMatrix(),
230b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                                           fHelper.usesLocalCoords()));
231df0c55785033c191d2d509c22662861588e4acd8joshualitt        if (!gp) {
232df0c55785033c191d2d509c22662861588e4acd8joshualitt            SkDebugf("Couldn't create a GrGeometryProcessor\n");
2331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        size_t vertexStride = gp->getVertexStride();
2371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
238b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        SkASSERT(fHelper.compatibleWithAlphaAsCoverage()
239b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                         ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)
240b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                         : vertexStride ==
241b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                   sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
2421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
243780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        int instanceCount = fPaths.count();
2441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int vertexCount = 0;
2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int indexCount = 0;
2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxVertices = DEFAULT_BUFFER_SIZE;
2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxIndices = DEFAULT_BUFFER_SIZE;
249002c2ce66be69d41632c9603ce62c50f04156518mtklein        uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride);
250002c2ce66be69d41632c9603ce62c50f04156518mtklein        uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t));
2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        for (int i = 0; i < instanceCount; i++) {
252780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            const PathData& args = fPaths[i];
2538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth,
2548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                       args.fJoin, args.fMiterLimit);
2551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                continue;
2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentIndices = tess.numIndices();
2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkASSERT(currentIndices <= UINT16_MAX);
2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > UINT16_MAX) {
263002c2ce66be69d41632c9603ce62c50f04156518mtklein                // if we added the current instance, we would overflow the indices we can store in a
2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                // uint16_t. Draw what we've got so far and reset.
265b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices,
266b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                           indexCount, indices);
2671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                vertexCount = 0;
2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                indexCount = 0;
2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentVertices = tess.numPts();
2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (vertexCount + currentVertices > maxVertices) {
2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
273002c2ce66be69d41632c9603ce62c50f04156518mtklein                vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride);
2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > maxIndices) {
2761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
277002c2ce66be69d41632c9603ce62c50f04156518mtklein                indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t));
2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
280002c2ce66be69d41632c9603ce62c50f04156518mtklein            extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor,
281b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                          vertexCount, indices + indexCount,
282b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                          fHelper.compatibleWithAlphaAsCoverage());
2831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            vertexCount += currentVertices;
2841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            indexCount += currentIndices;
2851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
286b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount,
287b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                   indices);
288002c2ce66be69d41632c9603ce62c50f04156518mtklein        sk_free(vertices);
289002c2ce66be69d41632c9603ce62c50f04156518mtklein        sk_free(indices);
2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
29225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
293780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>();
294b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon        if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
2958cab9a7685e872427e6f0388f149575a9b6016eejoshualitt            return false;
2968cab9a7685e872427e6f0388f149575a9b6016eejoshualitt        }
2978cab9a7685e872427e6f0388f149575a9b6016eejoshualitt
298780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
29988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->joinBounds(*that);
3001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return true;
3011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
303780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; }
3041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    struct PathData {
3060432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        GrColor fColor;
3070432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkMatrix fViewMatrix;
3080432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkPath fPath;
3090432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkScalar fStrokeWidth;
3108c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkStrokeRec::Style fStyle;
3110432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkPaint::Join fJoin;
3120432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkScalar fMiterLimit;
3130432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    };
3140432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon
315780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    SkSTArray<1, PathData, true> fPaths;
316b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    Helper fHelper;
3171b55a963a2374a14bb82eb887bb99ee91680f0ebreed
318b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    typedef GrMeshDrawOp INHERITED;
3191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas};
3201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
321b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon}  // anonymous namespace
322b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon
3230aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
3241105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
325de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt                              "GrAALinearizingConvexPathRenderer::onDrawPath");
3267c8460e10135c05a42d0744b84838bbc24398ac2Brian Salomon    SkASSERT(GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType());
3278acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    SkASSERT(!args.fShape->isEmpty());
3288c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkASSERT(!args.fShape->style().pathEffect());
329ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton
3300432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPath path;
3310432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    args.fShape->asPath(&path);
3328acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    bool fill = args.fShape->style().isSimpleFill();
3338acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    const SkStrokeRec& stroke = args.fShape->style().strokeRec();
3340432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth();
3350432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin();
3360432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar miterLimit = stroke.getMiter();
3371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
338b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
339b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon            std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join,
340b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon            miterLimit, args.fUserStencilSettings);
341b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
3421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return true;
3431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////////////////////////
3461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3476f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS
3481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
349b295573c93e7a9a78ee736a399c256d7669b79beBrian SalomonGR_DRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) {
350780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
3510432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPath path = GrTest::TestPathConvex(random);
3528c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style,
35460c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby                                     SkStrokeRec::kStroke_Style,
3558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                     SkStrokeRec::kStrokeAndFill_Style };
3568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkStrokeRec::Style style = styles[random->nextU() % 3];
3588c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkScalar strokeWidth = -1.f;
3600432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPaint::Join join = SkPaint::kMiter_Join;
3610432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar miterLimit = 0.5f;
3628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkStrokeRec::kFill_Style != style) {
3648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        strokeWidth = random->nextRangeF(1.0f, 10.0f);
3658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (random->nextBool()) {
3668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            join = SkPaint::kMiter_Join;
3678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        } else {
3688c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            join = SkPaint::kBevel_Join;
3698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
3708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        miterLimit = random->nextRangeF(0.5f, 2.0f);
3718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    }
372b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context);
373b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon    return AAFlatteningConvexPathOp::Make(std::move(paint), viewMatrix, path, strokeWidth, style,
374b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon                                          join, miterLimit, stencilSettings);
3751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif
378