GrAALinearizingConvexPathRenderer.cpp revision 3de0aee181b8fe0013b15100cba7381eb0468db4
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
101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAAConvexTessellator.h"
111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrContext.h"
121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrDefaultGeoProcFactory.h"
135ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h"
141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrGeometryProcessor.h"
151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrInvariantOutput.h"
16742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h"
18bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon#include "GrPipelineBuilder.h"
19dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrProcessor.h"
206663acff010ce752e4bf778da81fa97448c9db31bsalomon#include "GrStyle.h"
211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h"
22dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "SkPathPriv.h"
231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h"
241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h"
25e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h"
26895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h"
271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const int DEFAULT_BUFFER_SIZE = 100;
29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For
31bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// the time being, we simply drop back to software rendering above this stroke width.
32bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kMaxStrokeWidth = 20.0;
331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////
381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
390aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
400e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon    if (GrAAType::kCoverage != args.fAAType) {
41bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
42bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
438acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (!args.fShape->knownToBeConvex()) {
44bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
45bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
468acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->style().pathEffect()) {
47bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
48bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
498acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->inverseFilled()) {
506663acff010ce752e4bf778da81fa97448c9db31bsalomon        return false;
516663acff010ce752e4bf778da81fa97448c9db31bsalomon    }
528acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    const SkStrokeRec& stroke = args.fShape->style().strokeRec();
538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
56fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        if (!args.fViewMatrix->isSimilarity()) {
57fea7763140ba74b78f2c30028452e250140b6f21ethannicholas            return false;
58fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        }
596663acff010ce752e4bf778da81fa97448c9db31bsalomon        SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
618c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            return false;
628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        return strokeWidth <= kMaxStrokeWidth &&
648acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon               args.fShape->knownToBeClosed() &&
656663acff010ce752e4bf778da81fa97448c9db31bsalomon               stroke.getJoin() != SkPaint::Join::kRound_Join;
66bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
676663acff010ce752e4bf778da81fa97448c9db31bsalomon    return stroke.getStyle() == SkStrokeRec::kFill_Style;
681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator
711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess,
721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          void* vertices,
731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          size_t vertexStride,
741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          GrColor color,
751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t firstIndex,
761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t* idxs,
771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          bool tweakAlphaForCoverage) {
781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    intptr_t verts = reinterpret_cast<intptr_t>(vertices);
791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    // Make 'verts' point to the colors
851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    verts += sizeof(SkPoint);
861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (tweakAlphaForCoverage) {
88bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
89bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        } else {
931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
94002c2ce66be69d41632c9603ce62c50f04156518mtklein            *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
95bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    tess.coverage(i);
961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numIndices(); ++i) {
1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        idxs[i] = tess.index(i) + firstIndex;
1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
10406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemanstatic sk_sp<GrGeometryProcessor> create_fill_gp(bool tweakAlphaForCoverage,
105df0c55785033c191d2d509c22662861588e4acd8joshualitt                                                 const SkMatrix& viewMatrix,
1068c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                 bool usesLocalCoords) {
107df0c55785033c191d2d509c22662861588e4acd8joshualitt    using namespace GrDefaultGeoProcFactory;
108df0c55785033c191d2d509c22662861588e4acd8joshualitt
109df0c55785033c191d2d509c22662861588e4acd8joshualitt    Coverage::Type coverageType;
1108c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    if (tweakAlphaForCoverage) {
111df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kSolid_Type;
112df0c55785033c191d2d509c22662861588e4acd8joshualitt    } else {
113df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kAttribute_Type;
1141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1158c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    LocalCoords::Type localCoordsType =
1168c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
1173de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
1183de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon                              viewMatrix);
1191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
121780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp {
1221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholaspublic:
12325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
124f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon    static std::unique_ptr<GrDrawOp> Make(GrColor color,
125f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          const SkMatrix& viewMatrix,
126f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          const SkPath& path,
127f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          SkScalar strokeWidth,
128f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          SkStrokeRec::Style style,
129f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          SkPaint::Join join,
130f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                                          SkScalar miterLimit) {
131f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon        return std::unique_ptr<GrDrawOp>(new AAFlatteningConvexPathOp(
132f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                color, viewMatrix, path, strokeWidth, style, join, miterLimit));
1331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
135780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    const char* name() const override { return "AAFlatteningConvexPathOp"; }
1367c3e7180948766321c51d165737555e78910de51Brian Salomon
1377c3e7180948766321c51d165737555e78910de51Brian Salomon    SkString dumpInfo() const override {
1387c3e7180948766321c51d165737555e78910de51Brian Salomon        SkString string;
139780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        for (const auto& path : fPaths) {
140780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            string.appendf(
141780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, "
142780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    "MiterLimit: %.2f\n",
143780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit);
1447c3e7180948766321c51d165737555e78910de51Brian Salomon        }
1457c3e7180948766321c51d165737555e78910de51Brian Salomon        string.append(DumpPipelineInfo(*this->pipeline()));
1467c3e7180948766321c51d165737555e78910de51Brian Salomon        string.append(INHERITED::dumpInfo());
1477c3e7180948766321c51d165737555e78910de51Brian Salomon        return string;
1487c3e7180948766321c51d165737555e78910de51Brian Salomon    }
1491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
150e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate:
151780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    AAFlatteningConvexPathOp(GrColor color,
152780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkMatrix& viewMatrix,
153780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkPath& path,
154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkScalar strokeWidth,
155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkStrokeRec::Style style,
156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkPaint::Join join,
157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkScalar miterLimit)
158780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            : INHERITED(ClassID()) {
159780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        fPaths.emplace_back(
160780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit});
161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        // compute bounds
163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkRect bounds = path.getBounds();
164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkScalar w = strokeWidth;
165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        if (w > 0) {
166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            w /= 2;
167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            // If the half stroke width is < 1 then we effectively fallback to bevel joins.
168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            if (SkPaint::kMiter_Join == join && w > 1.f) {
169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                w *= miterLimit;
170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            }
171780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            bounds.outset(w, w);
172780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        }
173780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
174780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    }
175780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
17692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
17792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        input->pipelineColorInput()->setKnownFourComponents(fPaths[0].fColor);
17892aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        input->pipelineCoverageInput()->setUnknownSingleComponent();
17992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    }
18092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon
18192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon    void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
18292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        optimizations.getOverrideColorIfSet(&fPaths[0].fColor);
18392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        fUsesLocalCoords = optimizations.readsLocalCoords();
18492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon        fCanTweakAlphaForCoverage = optimizations.canTweakAlphaForCoverage();
1851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
187dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon    void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, int vertexCount,
188144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt              size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const {
1891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (vertexCount == 0 || indexCount == 0) {
1901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
192397536cabe12a9936659870dd220c869789424bacdalton        const GrBuffer* vertexBuffer;
1930e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrMesh mesh;
1941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int firstVertex;
195002c2ce66be69d41632c9603ce62c50f04156518mtklein        void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
1967539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon                                              &firstVertex);
1971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!verts) {
1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate vertices\n");
1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(verts, vertices, vertexCount * vertexStride);
2021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
203397536cabe12a9936659870dd220c869789424bacdalton        const GrBuffer* indexBuffer;
2041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int firstIndex;
2057539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!idxs) {
2071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate indices\n");
2081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(idxs, indices, indexCount * sizeof(uint16_t));
2110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
2120e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                         firstIndex, vertexCount, indexCount);
213342bfc25de5b0452b1551bf9db4bf45eac7718b2bsalomon        target->draw(gp, mesh);
2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
215002c2ce66be69d41632c9603ce62c50f04156518mtklein
216144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt    void onPrepareDraws(Target* target) const override {
2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
219df0c55785033c191d2d509c22662861588e4acd8joshualitt        // Setup GrGeometryProcessor
2208c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon        sk_sp<GrGeometryProcessor> gp(create_fill_gp(
2218c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                canTweakAlphaForCoverage, this->viewMatrix(), this->usesLocalCoords()));
222df0c55785033c191d2d509c22662861588e4acd8joshualitt        if (!gp) {
223df0c55785033c191d2d509c22662861588e4acd8joshualitt            SkDebugf("Couldn't create a GrGeometryProcessor\n");
2241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
2251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        size_t vertexStride = gp->getVertexStride();
2281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(canTweakAlphaForCoverage ?
2301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
2311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
2321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
233780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        int instanceCount = fPaths.count();
2341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int vertexCount = 0;
2361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int indexCount = 0;
2371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxVertices = DEFAULT_BUFFER_SIZE;
2381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxIndices = DEFAULT_BUFFER_SIZE;
239002c2ce66be69d41632c9603ce62c50f04156518mtklein        uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride);
240002c2ce66be69d41632c9603ce62c50f04156518mtklein        uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t));
2411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        for (int i = 0; i < instanceCount; i++) {
242780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            const PathData& args = fPaths[i];
2438c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth,
2448c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                       args.fJoin, args.fMiterLimit);
2451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                continue;
2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentIndices = tess.numIndices();
2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkASSERT(currentIndices <= UINT16_MAX);
2521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > UINT16_MAX) {
253002c2ce66be69d41632c9603ce62c50f04156518mtklein                // if we added the current instance, we would overflow the indices we can store in a
2541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                // uint16_t. Draw what we've got so far and reset.
25506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                this->draw(target, gp.get(),
25606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                           vertexCount, vertexStride, vertices, indexCount, indices);
2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                vertexCount = 0;
2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                indexCount = 0;
2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentVertices = tess.numPts();
2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (vertexCount + currentVertices > maxVertices) {
2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
263002c2ce66be69d41632c9603ce62c50f04156518mtklein                vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride);
2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > maxIndices) {
2661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
267002c2ce66be69d41632c9603ce62c50f04156518mtklein                indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t));
2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
270002c2ce66be69d41632c9603ce62c50f04156518mtklein            extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor,
2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                    vertexCount, indices + indexCount, canTweakAlphaForCoverage);
2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            vertexCount += currentVertices;
2731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            indexCount += currentIndices;
2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
27506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        this->draw(target, gp.get(), vertexCount, vertexStride, vertices, indexCount, indices);
276002c2ce66be69d41632c9603ce62c50f04156518mtklein        sk_free(vertices);
277002c2ce66be69d41632c9603ce62c50f04156518mtklein        sk_free(indices);
2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
28025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
281780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>();
282abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
283abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                                    that->bounds(), caps)) {
2848cab9a7685e872427e6f0388f149575a9b6016eejoshualitt            return false;
2858cab9a7685e872427e6f0388f149575a9b6016eejoshualitt        }
2868cab9a7685e872427e6f0388f149575a9b6016eejoshualitt
2871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
2881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
2891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return false;
2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
292780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        // In the event of two ops, one who can tweak, one who cannot, we just fall back to not
293780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        // tweaking
2941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
295780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            fCanTweakAlphaForCoverage = false;
2961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
298780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
29988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->joinBounds(*that);
3001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return true;
3011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
303780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    bool usesLocalCoords() const { return fUsesLocalCoords; }
304780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    bool canTweakAlphaForCoverage() const { return fCanTweakAlphaForCoverage; }
305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; }
3061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
307780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    struct PathData {
3080432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        GrColor fColor;
3090432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkMatrix fViewMatrix;
3100432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkPath fPath;
3110432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkScalar fStrokeWidth;
3128c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkStrokeRec::Style fStyle;
3130432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkPaint::Join fJoin;
3140432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon        SkScalar fMiterLimit;
3150432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    };
3160432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon
317780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    bool fUsesLocalCoords;
318780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    bool fCanTweakAlphaForCoverage;
319780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    SkSTArray<1, PathData, true> fPaths;
3201b55a963a2374a14bb82eb887bb99ee91680f0ebreed
321dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon    typedef GrMeshDrawOp INHERITED;
3221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas};
3231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3240aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
3251105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
326de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt                              "GrAALinearizingConvexPathRenderer::onDrawPath");
3271105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    SkASSERT(!args.fRenderTargetContext->isUnifiedMultisampled());
3288acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    SkASSERT(!args.fShape->isEmpty());
3298c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkASSERT(!args.fShape->style().pathEffect());
330ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton
3310432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPath path;
3320432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    args.fShape->asPath(&path);
3338acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    bool fill = args.fShape->style().isSimpleFill();
3348acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    const SkStrokeRec& stroke = args.fShape->style().strokeRec();
3350432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth();
3360432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin();
3370432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar miterLimit = stroke.getMiter();
3381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
339f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon    std::unique_ptr<GrDrawOp> op =
34082f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon            AAFlatteningConvexPathOp::Make(args.fPaint.getColor(), *args.fViewMatrix, path,
341780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                                           strokeWidth, stroke.getStyle(), join, miterLimit);
342976f5f0dc5e907d1ca50685fad117bd15d7fc87brobertphillips
34382f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon    GrPipelineBuilder pipelineBuilder(std::move(args.fPaint), args.fAAType);
344bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon    pipelineBuilder.setUserStencil(args.fUserStencilSettings);
345bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon
34624f19780d1e76595c049d8cad4352de839cfc6b5Brian Salomon    args.fRenderTargetContext->addDrawOp(pipelineBuilder, *args.fClip, std::move(op));
347bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon
3481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return true;
3491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////////////////////////
3521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#ifdef GR_TEST_UTILS
3541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3555ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) {
3560432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    GrColor color = GrRandomColor(random);
357780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
3580432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPath path = GrTest::TestPathConvex(random);
3598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style,
36160c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby                                     SkStrokeRec::kStroke_Style,
3628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                     SkStrokeRec::kStrokeAndFill_Style };
3638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkStrokeRec::Style style = styles[random->nextU() % 3];
3658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkScalar strokeWidth = -1.f;
3670432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkPaint::Join join = SkPaint::kMiter_Join;
3680432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon    SkScalar miterLimit = 0.5f;
3698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
3708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkStrokeRec::kFill_Style != style) {
3718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        strokeWidth = random->nextRangeF(1.0f, 10.0f);
3728c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (random->nextBool()) {
3738c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            join = SkPaint::kMiter_Join;
3748c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        } else {
3758c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            join = SkPaint::kBevel_Join;
3768c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
3778c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        miterLimit = random->nextRangeF(0.5f, 2.0f);
3788c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    }
3798c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
380780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    return AAFlatteningConvexPathOp::Make(color, viewMatrix, path, strokeWidth, style, join,
3815ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon                                          miterLimit);
3821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif
385