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"
15742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h"
17bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon#include "GrPipelineBuilder.h"
18dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrProcessor.h"
196663acff010ce752e4bf778da81fa97448c9db31bsalomon#include "GrStyle.h"
201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h"
21dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "SkPathPriv.h"
221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h"
231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h"
24e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h"
25895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h"
261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
27bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const int DEFAULT_BUFFER_SIZE = 100;
28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For
30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// the time being, we simply drop back to software rendering above this stroke width.
31bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kMaxStrokeWidth = 20.0;
321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////
371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
380aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
390e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon    if (GrAAType::kCoverage != args.fAAType) {
40bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
41bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
428acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (!args.fShape->knownToBeConvex()) {
43bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
44bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
458acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->style().pathEffect()) {
46bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
47bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
488acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    if (args.fShape->inverseFilled()) {
496663acff010ce752e4bf778da81fa97448c9db31bsalomon        return false;
506663acff010ce752e4bf778da81fa97448c9db31bsalomon    }
518acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon    const SkStrokeRec& stroke = args.fShape->style().strokeRec();
528c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
55fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        if (!args.fViewMatrix->isSimilarity()) {
56fea7763140ba74b78f2c30028452e250140b6f21ethannicholas            return false;
57fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        }
586663acff010ce752e4bf778da81fa97448c9db31bsalomon        SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            return false;
618c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        return strokeWidth <= kMaxStrokeWidth &&
638acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon               args.fShape->knownToBeClosed() &&
646663acff010ce752e4bf778da81fa97448c9db31bsalomon               stroke.getJoin() != SkPaint::Join::kRound_Join;
65bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
666663acff010ce752e4bf778da81fa97448c9db31bsalomon    return stroke.getStyle() == SkStrokeRec::kFill_Style;
671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator
701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess,
711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          void* vertices,
721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          size_t vertexStride,
731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          GrColor color,
741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t firstIndex,
751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t* idxs,
761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          bool tweakAlphaForCoverage) {
771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    intptr_t verts = reinterpret_cast<intptr_t>(vertices);
781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    // Make 'verts' point to the colors
841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    verts += sizeof(SkPoint);
851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (tweakAlphaForCoverage) {
87bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
88bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        } else {
921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
93002c2ce66be69d41632c9603ce62c50f04156518mtklein            *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
94bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    tess.coverage(i);
951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numIndices(); ++i) {
991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        idxs[i] = tess.index(i) + firstIndex;
1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
10306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemanstatic sk_sp<GrGeometryProcessor> create_fill_gp(bool tweakAlphaForCoverage,
104df0c55785033c191d2d509c22662861588e4acd8joshualitt                                                 const SkMatrix& viewMatrix,
1058c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon                                                 bool usesLocalCoords) {
106df0c55785033c191d2d509c22662861588e4acd8joshualitt    using namespace GrDefaultGeoProcFactory;
107df0c55785033c191d2d509c22662861588e4acd8joshualitt
108df0c55785033c191d2d509c22662861588e4acd8joshualitt    Coverage::Type coverageType;
1098c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    if (tweakAlphaForCoverage) {
110df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kSolid_Type;
111df0c55785033c191d2d509c22662861588e4acd8joshualitt    } else {
112df0c55785033c191d2d509c22662861588e4acd8joshualitt        coverageType = Coverage::kAttribute_Type;
1131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1148c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    LocalCoords::Type localCoordsType =
1158c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
1163de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
1173de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon                              viewMatrix);
1181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
1191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
120780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp {
1211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholaspublic:
12225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_CLASS_ID
123649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon    static std::unique_ptr<GrMeshDrawOp> Make(GrColor color,
124649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              const SkMatrix& viewMatrix,
125649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              const SkPath& path,
126649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              SkScalar strokeWidth,
127649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              SkStrokeRec::Style style,
128649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              SkPaint::Join join,
129649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon                                              SkScalar miterLimit) {
130649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon        return std::unique_ptr<GrMeshDrawOp>(new AAFlatteningConvexPathOp(
131f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon                color, viewMatrix, path, strokeWidth, style, join, miterLimit));
1321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
134780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    const char* name() const override { return "AAFlatteningConvexPathOp"; }
1357c3e7180948766321c51d165737555e78910de51Brian Salomon
1367c3e7180948766321c51d165737555e78910de51Brian Salomon    SkString dumpInfo() const override {
1377c3e7180948766321c51d165737555e78910de51Brian Salomon        SkString string;
138780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        for (const auto& path : fPaths) {
139780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            string.appendf(
140780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, "
141780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    "MiterLimit: %.2f\n",
142780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                    path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit);
1437c3e7180948766321c51d165737555e78910de51Brian Salomon        }
1447c3e7180948766321c51d165737555e78910de51Brian Salomon        string.append(DumpPipelineInfo(*this->pipeline()));
1457c3e7180948766321c51d165737555e78910de51Brian Salomon        string.append(INHERITED::dumpInfo());
1467c3e7180948766321c51d165737555e78910de51Brian Salomon        return string;
1477c3e7180948766321c51d165737555e78910de51Brian Salomon    }
1481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
149e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate:
150780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    AAFlatteningConvexPathOp(GrColor color,
151780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkMatrix& viewMatrix,
152780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             const SkPath& path,
153780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkScalar strokeWidth,
154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkStrokeRec::Style style,
155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkPaint::Join join,
156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                             SkScalar miterLimit)
157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            : INHERITED(ClassID()) {
158780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        fPaths.emplace_back(
159780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit});
160780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        // compute bounds
162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkRect bounds = path.getBounds();
163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        SkScalar w = strokeWidth;
164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        if (w > 0) {
165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            w /= 2;
166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            // If the half stroke width is < 1 then we effectively fallback to bevel joins.
167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            if (SkPaint::kMiter_Join == join && w > 1.f) {
168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon                w *= miterLimit;
169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            }
170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon            bounds.outset(w, w);
171780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        }
172780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon        this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
173780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon    }
174780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon
175c0b642ca48d58416409e555549434066f09692b7Brian Salomon    void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color,
176c0b642ca48d58416409e555549434066f09692b7Brian Salomon                                            GrPipelineAnalysisCoverage* coverage) const override {
177c0b642ca48d58416409e555549434066f09692b7Brian Salomon        color->setToConstant(fPaths[0].fColor);
178c0b642ca48d58416409e555549434066f09692b7Brian Salomon        *coverage = GrPipelineAnalysisCoverage::kSingleChannel;
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
339649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon    std::unique_ptr<GrMeshDrawOp> 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
346649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon    args.fRenderTargetContext->addMeshDrawOp(pipelineBuilder, *args.fClip, std::move(op));
347bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon
3481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return true;
3491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////////////////////////
3521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3536f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if 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