GrAALinearizingConvexPathRenderer.cpp revision 1a1b3ac0d4feecb0fefa8a07c7abf3471c96f545
11a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
21a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/*
31a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Copyright 2015 Google Inc.
41a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *
51a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Use of this source code is governed by a BSD-style license that can be
61a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * found in the LICENSE file.
71a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas */
81a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
91a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAALinearizingConvexPathRenderer.h"
101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAAConvexTessellator.h"
121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrBatch.h"
131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrBatchTarget.h"
141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrBatchTest.h"
151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrContext.h"
161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrDefaultGeoProcFactory.h"
171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrGeometryProcessor.h"
181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrInvariantOutput.h"
191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h"
201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrProcessor.h"
211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPipelineBuilder.h"
221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrStrokeInfo.h"
231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h"
241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h"
251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h"
261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "gl/GrGLProcessor.h"
271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "gl/GrGLSL.h"
281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "gl/GrGLGeometryProcessor.h"
291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "gl/builders/GrGLProgramBuilder.h"
301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#define DEFAULT_BUFFER_SIZE 100
321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////
371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasbool GrAALinearizingConvexPathRenderer::canDrawPath(const GrDrawTarget* target,
391a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                    const GrPipelineBuilder*,
401a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                    const SkMatrix& viewMatrix,
411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                    const SkPath& path,
421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                    const GrStrokeInfo& stroke,
431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                    bool antiAlias) const {
441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return (antiAlias && stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator
481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess,
491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          void* vertices,
501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          size_t vertexStride,
511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          GrColor color,
521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t firstIndex,
531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          uint16_t* idxs,
541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                          bool tweakAlphaForCoverage) {
551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    intptr_t verts = reinterpret_cast<intptr_t>(vertices);
561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    // Make 'verts' point to the colors
621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    verts += sizeof(SkPoint);
631a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numPts(); ++i) {
641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(tess.depth(i) >= -0.5f && tess.depth(i) <= 0.5f);
651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (tweakAlphaForCoverage) {
661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkASSERT(SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f)) <= 255);
671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            unsigned scale = SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f));
681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        } else {
711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                                    tess.depth(i) + 0.5f;
741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < tess.numIndices(); ++i) {
781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        idxs[i] = tess.index(i) + firstIndex;
791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage,
831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                 const SkMatrix& localMatrix,
841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                 bool usesLocalCoords,
851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                 bool coverageIgnored) {
861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType;
871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    if (!tweakAlphaForCoverage) {
881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        flags |= GrDefaultGeoProcFactory::kCoverage_GPType;
891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE, usesLocalCoords, coverageIgnored,
921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                           SkMatrix::I(), localMatrix);
931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasclass AAFlatteningConvexPathBatch : public GrBatch {
961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholaspublic:
971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    struct Geometry {
981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        GrColor fColor;
991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkMatrix fViewMatrix;
1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkPath fPath;
1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    };
1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    static GrBatch* Create(const Geometry& geometry) {
1041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return SkNEW_ARGS(AAFlatteningConvexPathBatch, (geometry));
1051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    const char* name() const override { return "AAConvexBatch"; }
1081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
1101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // When this is called on a batch, there is only one geometry bundle
1111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        out->setKnownFourComponents(fGeoData[0].fColor);
1121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
1141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        out->setUnknownSingleComponent();
1151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    void initBatchTracker(const GrPipelineInfo& init) override {
1181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // Handle any color overrides
1191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (init.fColorIgnored) {
1201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            fGeoData[0].fColor = GrColor_ILLEGAL;
1211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        } else if (GrColor_ILLEGAL != init.fOverrideColor) {
1221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            fGeoData[0].fColor = init.fOverrideColor;
1231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
1241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // setup batch properties
1261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fColorIgnored = init.fColorIgnored;
1271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fColor = fGeoData[0].fColor;
1281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
1291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fCoverageIgnored = init.fCoverageIgnored;
1301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fLinesOnly = SkPath::kLine_SegmentMask == fGeoData[0].fPath.getSegmentMasks();
1311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage;
1321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    void draw(GrBatchTarget* batchTarget, const GrPipeline* pipeline, int vertexCount,
1351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) {
1361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (vertexCount == 0 || indexCount == 0) {
1371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
1391a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        const GrVertexBuffer* vertexBuffer;
1401a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        GrVertices info;
1411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int firstVertex;
1421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount, &vertexBuffer,
1431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                &firstVertex);
1441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!verts) {
1451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate vertices\n");
1461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
1481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(verts, vertices, vertexCount * vertexStride);
1491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        const GrIndexBuffer* indexBuffer;
1511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int firstIndex;
1521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        uint16_t* idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
1531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (!idxs) {
1541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not allocate indices\n");
1551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
1571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        memcpy(idxs, indices, indexCount * sizeof(uint16_t));
1581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
1591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                firstIndex, vertexCount, indexCount);
1601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        batchTarget->draw(info);
1611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
1621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1631a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
1641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
1651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkMatrix invert;
1671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
1681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkDebugf("Could not invert viewmatrix\n");
1691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return;
1701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
1711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // Setup GrGeometryProcessor
1731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkAutoTUnref<const GrGeometryProcessor> gp(
1741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                create_fill_gp(canTweakAlphaForCoverage, invert,
1751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                               this->usesLocalCoords(),
1761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                               this->coverageIgnored()));
1771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        batchTarget->initDraw(gp, pipeline);
1791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        size_t vertexStride = gp->getVertexStride();
1811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(canTweakAlphaForCoverage ?
1831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
1841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
1851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        GrAAConvexTessellator tess;
1871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int instanceCount = fGeoData.count();
1891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int vertexCount = 0;
1911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int indexCount = 0;
1921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxVertices = DEFAULT_BUFFER_SIZE;
1931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        int maxIndices = DEFAULT_BUFFER_SIZE;
1941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        uint8_t* vertices = (uint8_t*) malloc(maxVertices * vertexStride);
1951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        uint16_t* indices = (uint16_t*) malloc(maxIndices * sizeof(uint16_t));
1961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        for (int i = 0; i < instanceCount; i++) {
1971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            tess.rewind();
1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            Geometry& args = fGeoData[i];
2001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
2021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                continue;
2031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentIndices = tess.numIndices();
2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            SkASSERT(currentIndices <= UINT16_MAX);
2071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > UINT16_MAX) {
2081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                // if we added the current instance, we would overflow the indices we can store in a
2091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                // uint16_t. Draw what we've got so far and reset.
2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCount,
2111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                        indices);
2121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                vertexCount = 0;
2131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                indexCount = 0;
2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            int currentVertices = tess.numPts();
2161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (vertexCount + currentVertices > maxVertices) {
2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                vertices = (uint8_t*) realloc(vertices, maxVertices * vertexStride);
2191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            if (indexCount + currentIndices > maxIndices) {
2211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
2221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                indices = (uint16_t*) realloc(indices, maxIndices * sizeof(uint16_t));
2231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            }
2241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor,
2261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                    vertexCount, indices + indexCount, canTweakAlphaForCoverage);
2271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            vertexCount += currentVertices;
2281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            indexCount += currentIndices;
2291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCount, indices);
2311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        free(vertices);
2321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        free(indices);
2331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
2361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasprivate:
2381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    AAFlatteningConvexPathBatch(const Geometry& geometry) {
2391a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        this->initClassID<AAFlatteningConvexPathBatch>();
2401a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fGeoData.push_back(geometry);
2411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // compute bounds
2431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fBounds = geometry.fPath.getBounds();
2441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        geometry.fViewMatrix.mapRect(&fBounds);
2451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    bool onCombineIfPossible(GrBatch* t) override {
2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        AAFlatteningConvexPathBatch* that = t->cast<AAFlatteningConvexPathBatch>();
2491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
2521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            return false;
2531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // In the event of two batches, one who can tweak, one who cannot, we just fall back to
2561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // not tweaking
2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            fBatch.fCanTweakAlphaForCoverage = false;
2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        }
2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        this->joinBounds(that->bounds());
2631a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return true;
2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    GrColor color() const { return fBatch.fColor; }
2671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    bool linesOnly() const { return fBatch.fLinesOnly; }
2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
2701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    struct BatchTracker {
2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        GrColor fColor;
2751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool fUsesLocalCoords;
2761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool fColorIgnored;
2771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool fCoverageIgnored;
2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool fLinesOnly;
2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        bool fCanTweakAlphaForCoverage;
2801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    };
2811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    BatchTracker fBatch;
2831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkSTArray<1, Geometry, true> fGeoData;
2841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas};
2851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
2861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasbool GrAALinearizingConvexPathRenderer::onDrawPath(GrDrawTarget* target,
2871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   GrPipelineBuilder* pipelineBuilder,
2881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   GrColor color,
2891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   const SkMatrix& vm,
2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   const SkPath& path,
2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   const GrStrokeInfo&,
2921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                                   bool antiAlias) {
2931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    if (path.isEmpty()) {
2941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return true;
2951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
2961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    AAFlatteningConvexPathBatch::Geometry geometry;
2971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fColor = color;
2981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fViewMatrix = vm;
2991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fPath = path;
3001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkAutoTUnref<GrBatch> batch(AAFlatteningConvexPathBatch::Create(geometry));
3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    target->drawBatch(pipelineBuilder, batch);
3031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return true;
3051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas///////////////////////////////////////////////////////////////////////////////////////////////////
3081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#ifdef GR_TEST_UTILS
3101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasBATCH_TEST_DEFINE(AAFlatteningConvexPathBatch) {
3121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    AAFlatteningConvexPathBatch::Geometry geometry;
3131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fColor = GrRandomColor(random);
3141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
3151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    geometry.fPath = GrTest::TestPathConvex(random);
3161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    return AAFlatteningConvexPathBatch::Create(geometry);
3181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
3191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
3201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif
321