169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com/*
369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Copyright 2012 Google Inc.
469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com *
569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * found in the LICENSE file.
769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com */
869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrAAConvexPathRenderer.h"
1069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
11e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips#include "GrAAConvexTessellator.h"
1227f398f04dff306418a142c27175eaa35d21a915joshualitt#include "GrBatch.h"
1327f398f04dff306418a142c27175eaa35d21a915joshualitt#include "GrBatchTarget.h"
148e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt#include "GrBatchTest.h"
1569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrContext.h"
16e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips#include "GrDefaultGeoProcFactory.h"
17c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h"
18eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrGeometryProcessor.h"
19605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
2069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrPathUtils.h"
218dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel#include "GrProcessor.h"
228dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel#include "GrPipelineBuilder.h"
231899651ffc459f5462aa989cd6d08507947b67e4kkinnunen#include "GrStrokeInfo.h"
24af18a09d13611526c4217656c98947f9067cb07aegdaniel#include "SkGeometry.h"
2569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkString.h"
26933e65d914eb86b1fbbf8ea9cf1da58ac7c42500commit-bot@chromium.org#include "SkTraceEvent.h"
27b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
2890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h"
29249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h"
30eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "gl/builders/GrGLProgramBuilder.h"
31234d4fba75aac009e34c088037fcd9e244798c40commit-bot@chromium.org
3269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comGrAAConvexPathRenderer::GrAAConvexPathRenderer() {
3369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
3469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct Segment {
3669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    enum {
379b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        // These enum values are assumed in member functions below.
389b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kLine = 0,
399b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        kQuad = 1,
4069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    } fType;
419b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com
429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // line uses one pt, quad uses 2 pts
43972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint fPts[2];
449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // normal to edge ending at each pt
45972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector fNorms[2];
469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // is the corner where the previous segment meets this segment
479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // sharp. If so, fMid is a normalized bisector facing outward.
48972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector fMid;
499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int countPoints() {
519b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
529b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fType + 1;
539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endPt() const {
559b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
569b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fPts[fType];
579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    const SkPoint& endNorm() const {
599b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
609b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com        return fNorms[fType];
619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    };
6269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
6369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
6469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray;
6569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
66fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void center_of_mass(const SegmentArray& segments, SkPoint* c) {
6781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar area = 0;
686390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint center = {0, 0};
699aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
706390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org    SkPoint p0 = {0, 0};
715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (count > 2) {
725b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // We translate the polygon so that the first point is at the origin.
735b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // This avoids some precision issues with small area polygons far away
745b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // from the origin.
755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        p0 = segments[0].endPt();
765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pi;
775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        SkPoint pj;
78a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        // the first and last iteration of the below loop would compute
795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // zeros since the starting / ending point is (0,0). So instead we start
805b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // at i=1 and make the last iteration i=count-2.
815b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        pj = segments[1].endPt() - p0;
825b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        for (int i = 1; i < count - 1; ++i) {
835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            pi = pj;
845b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            const SkPoint pj = segments[i + 1].endPt() - p0;
855b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
8681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY);
875b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            area += t;
885b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fX += (pi.fX + pj.fX) * t;
895b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com            center.fY += (pi.fY + pj.fY) * t;
905b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com
915b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        }
929aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // If the poly has no area then we instead return the average of
94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // its points.
955b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com    if (SkScalarNearlyZero(area)) {
96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkPoint avg;
97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.set(0, 0);
98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        for (int i = 0; i < count; ++i) {
99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            const SkPoint& pt = segments[i].endPt();
100278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fX += pt.fX;
101278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            avg.fY += pt.fY;
102278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        }
103278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        SkScalar denom = SK_Scalar1 / count;
104278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        avg.scale(denom);
105278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        *c = avg;
106278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
107278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        area *= 3;
10880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        area = SkScalarInvert(area);
10981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fX = SkScalarMul(center.fX, area);
11081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        center.fY = SkScalarMul(center.fY, area);
1115b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        // undo the translate of p0 to the origin.
1125b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com        *c = center + p0;
113278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
114f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY));
1159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
117fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void compute_vectors(SegmentArray* segments,
118fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            SkPoint* fanPt,
119fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            SkPath::Direction dir,
120fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            int* vCount,
121fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            int* iCount) {
1229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    center_of_mass(*segments, fanPt);
1239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments->count();
1249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
125278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    // Make the normals point towards the outside
126972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint::Side normSide;
127278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    if (dir == SkPath::kCCW_Direction) {
128972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        normSide = SkPoint::kRight_Side;
129278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    } else {
130972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        normSide = SkPoint::kLeft_Side;
131278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com    }
1329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1339aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *vCount = 0;
1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    *iCount = 0;
1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute normals at all points
1369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1377d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        Segment& sega = (*segments)[a];
1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
141972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        const SkPoint* prevPt = &sega.endPt();
1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int n = segb.countPoints();
1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        for (int p = 0; p < n; ++p) {
1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p] = segb.fPts[p] - *prevPt;
1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].normalize();
1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            segb.fNorms[p].setOrthog(segb.fNorms[p], normSide);
1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            prevPt = &segb.fPts[p];
1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 5;
1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 9;
1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        } else {
1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *vCount += 6;
1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            *iCount += 12;
1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        }
1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // compute mid-vectors where segments meet. TODO: Detect shallow corners
1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    // and leave out the wedges and close gaps by stitching segments together.
1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = (*segments)[a];
1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        Segment& segb = (*segments)[b];
1649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid = segb.fNorms[0] + sega.endNorm();
1659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        segb.fMid.normalize();
1669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // corner wedges
1679aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *vCount += 4;
1689aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        *iCount += 6;
1699aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    }
1709aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com}
1719aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData {
1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData() { fStage = kInitial; }
1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    bool isDegenerate() const { return kNonDegenerate != fStage; }
1759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    enum {
1769732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kInitial,
1779732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kPoint,
1789732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kLine,
1799732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        kNonDegenerate
1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }           fStage;
181972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint     fFirstPoint;
182972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkVector    fLineNormal;
18381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar    fLineC;
1849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com};
1859732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
186fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kClose = (SK_Scalar1 / 16);
187fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kCloseSqd = SkScalarMul(kClose, kClose);
1889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
189972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgstatic void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) {
1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    switch (data->fStage) {
1919732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kInitial:
1929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fFirstPoint = pt;
1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            data->fStage = DegenerateTestData::kPoint;
1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kPoint:
196fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org            if (pt.distanceToSqd(data->fFirstPoint) > kCloseSqd) {
1979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal = pt - data->fFirstPoint;
1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.normalize();
1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineNormal.setOrthog(data->fLineNormal);
2009732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fLineC = -data->fLineNormal.dot(data->fFirstPoint);
2019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kLine;
2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kLine:
205fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org            if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) {
2069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                data->fStage = DegenerateTestData::kNonDegenerate;
2079732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            }
2089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        case DegenerateTestData::kNonDegenerate:
2099732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com            break;
2109732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com        default:
21188cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org            SkFAIL("Unexpected degenerate test stage.");
2129732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    }
2139732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}
2149732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
215fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) {
216a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!path.cheapComputeDirection(dir)) {
217a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
218a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
219af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    // check whether m reverses the orientation
220f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(!m.hasPerspective());
22181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
22281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                      SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
223af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    if (det2x2 < 0) {
22430c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        *dir = SkPath::OppositeDirection(*dir);
225af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
226a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    return true;
227af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com}
228af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
229106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_line_to_segment(const SkPoint& pt,
23027f398f04dff306418a142c27175eaa35d21a915joshualitt                                       SegmentArray* segments) {
231fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->push_back();
232fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->back().fType = Segment::kLine;
233fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    segments->back().fPts[0] = pt;
234fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
235fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
236106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_quad_segment(const SkPoint pts[3],
23727f398f04dff306418a142c27175eaa35d21a915joshualitt                                    SegmentArray* segments) {
238fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || pts[1].distanceToSqd(pts[2]) < kCloseSqd) {
239fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        if (pts[0] != pts[2]) {
24027f398f04dff306418a142c27175eaa35d21a915joshualitt            add_line_to_segment(pts[2], segments);
241fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        }
242fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    } else {
243fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->push_back();
244fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fType = Segment::kQuad;
245fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fPts[0] = pts[1];
246fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org        segments->back().fPts[1] = pts[2];
247fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    }
248fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
249fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
250fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_cubic_segments(const SkPoint pts[4],
251fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                                      SkPath::Direction dir,
25227f398f04dff306418a142c27175eaa35d21a915joshualitt                                      SegmentArray* segments) {
253fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    SkSTArray<15, SkPoint, true> quads;
254fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads);
255fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    int count = quads.count();
256fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    for (int q = 0; q < count; q += 3) {
25727f398f04dff306418a142c27175eaa35d21a915joshualitt        add_quad_segment(&quads[q], segments);
258fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org    }
259fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org}
260fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org
261fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic bool get_segments(const SkPath& path,
262fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         const SkMatrix& m,
263fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         SegmentArray* segments,
264fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         SkPoint* fanPt,
265fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                         int* vCount,
26627f398f04dff306418a142c27175eaa35d21a915joshualitt                         int* iCount) {
26769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    SkPath::Iter iter(path, true);
26830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    // This renderer over-emphasizes very thin path regions. We use the distance
2695cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // to the path from the sample to compute coverage. Every pixel intersected
2705cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // by the path will be hit and the maximum distance is sqrt(2)/2. We don't
271fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // notice that the sample may be close to a very thin area of the path and
2725cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // thus should be very light. This is particularly egregious for degenerate
2735cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // line paths. We detect paths that are very close to a line (zero area) and
2745cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com    // draw nothing.
2759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com    DegenerateTestData degenerateData;
276a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    SkPath::Direction dir;
277a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    // get_direction can fail for some degenerate paths.
278a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    if (!get_direction(path, m, &dir)) {
279a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com        return false;
280a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com    }
2819732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com
28269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    for (;;) {
283972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        SkPoint pts[4];
28494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        SkPath::Verb verb = iter.next(pts);
28594b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com        switch (verb) {
28694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kMove_Verb:
2871a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 1);
2889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[0]);
2899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                break;
29094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kLine_Verb: {
291fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                m.mapPoints(&pts[1], 1);
2921a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
29327f398f04dff306418a142c27175eaa35d21a915joshualitt                add_line_to_segment(pts[1], segments);
29469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
29569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            }
29694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kQuad_Verb:
297fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                m.mapPoints(pts, 3);
2989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
2999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
30027f398f04dff306418a142c27175eaa35d21a915joshualitt                add_quad_segment(pts, segments);
30169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
302af18a09d13611526c4217656c98947f9067cb07aegdaniel            case SkPath::kConic_Verb: {
303af18a09d13611526c4217656c98947f9067cb07aegdaniel                m.mapPoints(pts, 3);
304af18a09d13611526c4217656c98947f9067cb07aegdaniel                SkScalar weight = iter.conicWeight();
305af18a09d13611526c4217656c98947f9067cb07aegdaniel                SkAutoConicToQuads converter;
306af18a09d13611526c4217656c98947f9067cb07aegdaniel                const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.5f);
307af18a09d13611526c4217656c98947f9067cb07aegdaniel                for (int i = 0; i < converter.countQuads(); ++i) {
308af18a09d13611526c4217656c98947f9067cb07aegdaniel                    update_degenerate_test(&degenerateData, quadPts[2*i + 1]);
309af18a09d13611526c4217656c98947f9067cb07aegdaniel                    update_degenerate_test(&degenerateData, quadPts[2*i + 2]);
31027f398f04dff306418a142c27175eaa35d21a915joshualitt                    add_quad_segment(quadPts + 2*i, segments);
311af18a09d13611526c4217656c98947f9067cb07aegdaniel                }
312af18a09d13611526c4217656c98947f9067cb07aegdaniel                break;
313af18a09d13611526c4217656c98947f9067cb07aegdaniel            }
31494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kCubic_Verb: {
3151a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com                m.mapPoints(pts, 4);
3169732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[1]);
3179732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[2]);
3189732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                update_degenerate_test(&degenerateData, pts[3]);
31927f398f04dff306418a142c27175eaa35d21a915joshualitt                add_cubic_segments(pts, dir, segments);
32069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
32169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            };
32294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com            case SkPath::kDone_Verb:
3239732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                if (degenerateData.isDegenerate()) {
3249732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return false;
3259732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                } else {
326278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com                    compute_vectors(segments, fanPt, dir, vCount, iCount);
3279732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                    return true;
3289732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com                }
32969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com            default:
33069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com                break;
33169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
33269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
33369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
33469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
33569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex {
336972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint  fPos;
337972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkPoint  fUV;
33881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD0;
33981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    SkScalar fD1;
34069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com};
341fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3427d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comstruct Draw {
3437d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    Draw() : fVertexCnt(0), fIndexCnt(0) {}
3447d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int fVertexCnt;
3457d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int fIndexCnt;
3467d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com};
3477d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
3487d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comtypedef SkTArray<Draw, true> DrawArray;
3497d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
350fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void create_vertices(const SegmentArray&  segments,
351fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            const SkPoint& fanPt,
352fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            DrawArray*     draws,
353fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            QuadVertex*    verts,
354fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org                            uint16_t*      idxs) {
3557d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    Draw* draw = &draws->push_back();
3567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    // alias just to make vert/index assignments easier to read.
3577d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int* v = &draw->fVertexCnt;
3587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    int* i = &draw->fIndexCnt;
35969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
3609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    int count = segments.count();
3619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com    for (int a = 0; a < count; ++a) {
3629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& sega = segments[a];
3639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        int b = (a + 1) % count;
3649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        const Segment& segb = segments[b];
365fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        // Check whether adding the verts for this segment to the current draw would cause index
3677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        // values to overflow.
3687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        int vCount = 4;
3697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        if (Segment::kLine == segb.fType) {
3707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            vCount += 5;
3717d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        } else {
3727d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            vCount += 6;
3737d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        }
3747d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        if (draw->fVertexCnt + vCount > (1 << 16)) {
3757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts += *v;
3767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs += *i;
3777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            draw = &draws->push_back();
3787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            v = &draw->fVertexCnt;
3797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            i = &draw->fIndexCnt;
3807d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        }
3817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
3829aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        // FIXME: These tris are inset in the 1 unit arc around the corner
3837d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fPos = sega.endPt();
3847d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm();
3857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid;
3867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0];
3877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fUV.set(0,0);
3887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fUV.set(0,-SK_Scalar1);
3897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fUV.set(0,-SK_Scalar1);
3907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fUV.set(0,-SK_Scalar1);
3917d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1;
3927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1;
3937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1;
3947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1;
3957d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
3967d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 0] = *v + 0;
3977d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 1] = *v + 2;
3987d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 2] = *v + 1;
3997d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 3] = *v + 0;
4007d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 4] = *v + 3;
4017d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        idxs[*i + 5] = *v + 2;
4027d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4037d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        *v += 4;
4047d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com        *i += 6;
40569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
4069aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com        if (Segment::kLine == segb.fType) {
4077d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fPos = fanPt;
4087d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fPos = sega.endPt();
4097d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fPos = segb.fPts[0];
4109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4117d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0];
4127d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0];
4139aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // we draw the line edge as a degenerate quad (u is 0, v is the
4159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            // signed distance to the edge)
4167d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos,
4177d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com                                                        verts[*v + 2].fPos);
4187d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fUV.set(0, dist);
4197d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fUV.set(0, 0);
4207d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fUV.set(0, 0);
4217d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fUV.set(0, -SK_Scalar1);
4227d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fUV.set(0, -SK_Scalar1);
4237d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4247d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1;
4257d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1;
4267d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1;
4277d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1;
4287d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1;
4297d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4303596482cc7b36c9f45f59c304dfb28a841229525cdalton            idxs[*i + 0] = *v + 3;
4313596482cc7b36c9f45f59c304dfb28a841229525cdalton            idxs[*i + 1] = *v + 1;
4323596482cc7b36c9f45f59c304dfb28a841229525cdalton            idxs[*i + 2] = *v + 2;
4337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4343596482cc7b36c9f45f59c304dfb28a841229525cdalton            idxs[*i + 3] = *v + 4;
4353596482cc7b36c9f45f59c304dfb28a841229525cdalton            idxs[*i + 4] = *v + 3;
4367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 5] = *v + 2;
4377d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4383596482cc7b36c9f45f59c304dfb28a841229525cdalton            *i += 6;
4393596482cc7b36c9f45f59c304dfb28a841229525cdalton
4403596482cc7b36c9f45f59c304dfb28a841229525cdalton            // Draw the interior fan if it exists.
4413596482cc7b36c9f45f59c304dfb28a841229525cdalton            // TODO: Detect and combine colinear segments. This will ensure we catch every case
4423596482cc7b36c9f45f59c304dfb28a841229525cdalton            // with no interior, and that the resulting shared edge uses the same endpoints.
4433596482cc7b36c9f45f59c304dfb28a841229525cdalton            if (count >= 3) {
4443596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 0] = *v + 0;
4453596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 1] = *v + 2;
4463596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 2] = *v + 1;
4473596482cc7b36c9f45f59c304dfb28a841229525cdalton
4483596482cc7b36c9f45f59c304dfb28a841229525cdalton                *i += 3;
4493596482cc7b36c9f45f59c304dfb28a841229525cdalton            }
4507d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
4517d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *v += 5;
452068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com        } else {
453972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
4549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
455972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            SkVector midVec = segb.fNorms[0] + segb.fNorms[1];
4569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            midVec.normalize();
4579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fPos = fanPt;
4597d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fPos = qpts[0];
4607d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fPos = qpts[2];
4617d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fPos = qpts[0] + segb.fNorms[0];
4627d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fPos = qpts[2] + segb.fNorms[1];
4637d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fPos = qpts[1] + midVec;
4649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
46581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com            SkScalar c = segb.fNorms[0].dot(qpts[0]);
4667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD0 =  -segb.fNorms[0].dot(fanPt) + c;
4677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD0 =  0.f;
4687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD0 =  -segb.fNorms[0].dot(qpts[2]) + c;
4697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD0 = -SK_ScalarMax/100;
4707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD0 = -SK_ScalarMax/100;
4717d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fD0 = -SK_ScalarMax/100;
4729aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com            c = segb.fNorms[1].dot(qpts[2]);
4747d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 0].fD1 =  -segb.fNorms[1].dot(fanPt) + c;
4757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 1].fD1 =  -segb.fNorms[1].dot(qpts[0]) + c;
4767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 2].fD1 =  0.f;
4777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 3].fD1 = -SK_ScalarMax/100;
4787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 4].fD1 = -SK_ScalarMax/100;
4797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            verts[*v + 5].fD1 = -SK_ScalarMax/100;
4809aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4811971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com            GrPathUtils::QuadUVMatrix toUV(qpts);
482972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            toUV.apply<6, sizeof(QuadVertex), sizeof(SkPoint)>(verts + *v);
4839aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4847d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 0] = *v + 3;
4857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 1] = *v + 1;
4867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 2] = *v + 2;
4877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 3] = *v + 4;
4887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 4] = *v + 3;
4897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 5] = *v + 2;
4909aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4917d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 6] = *v + 5;
4927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 7] = *v + 3;
4937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            idxs[*i + 8] = *v + 4;
4949aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
4953596482cc7b36c9f45f59c304dfb28a841229525cdalton            *i += 9;
4963596482cc7b36c9f45f59c304dfb28a841229525cdalton
4973596482cc7b36c9f45f59c304dfb28a841229525cdalton            // Draw the interior fan if it exists.
4983596482cc7b36c9f45f59c304dfb28a841229525cdalton            // TODO: Detect and combine colinear segments. This will ensure we catch every case
4993596482cc7b36c9f45f59c304dfb28a841229525cdalton            // with no interior, and that the resulting shared edge uses the same endpoints.
5003596482cc7b36c9f45f59c304dfb28a841229525cdalton            if (count >= 3) {
5013596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 0] = *v + 0;
5023596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 1] = *v + 2;
5033596482cc7b36c9f45f59c304dfb28a841229525cdalton                idxs[*i + 2] = *v + 1;
5043596482cc7b36c9f45f59c304dfb28a841229525cdalton
5053596482cc7b36c9f45f59c304dfb28a841229525cdalton                *i += 3;
5063596482cc7b36c9f45f59c304dfb28a841229525cdalton            }
5079aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com
5087d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com            *v += 6;
50969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        }
51069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
51169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
51269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/*
51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed
51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in
51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated
52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to
521041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad.
522041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support.
52390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */
52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
525249af15fb82833d2274850c589812b6e69df0033joshualittclass QuadEdgeEffect : public GrGeometryProcessor {
52690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic:
52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
528d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    static GrGeometryProcessor* Create(GrColor color, const SkMatrix& localMatrix) {
529d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt        return SkNEW_ARGS(QuadEdgeEffect, (color, localMatrix));
53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    virtual ~QuadEdgeEffect() {}
53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "QuadEdge"; }
53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
53671c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* inPosition() const { return fInPosition; }
53771c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* inQuadEdge() const { return fInQuadEdge; }
53888c23fc6e8ed0243159fd17d815b4f813805647bjoshualitt    GrColor color() const { return fColor; }
539e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt    const SkMatrix& localMatrix() const { return fLocalMatrix; }
540249af15fb82833d2274850c589812b6e69df0033joshualitt
541b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    class GLProcessor : public GrGLGeometryProcessor {
54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    public:
543eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        GLProcessor(const GrGeometryProcessor&,
5449b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                    const GrBatchTracker&)
5459b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            : fColor(GrColor_ILLEGAL) {}
54690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
54736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
5482dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>();
5499b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLGPBuilder* pb = args.fPB;
5509b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
5512dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
552abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // emit attributes
553abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            vsBuilder->emitAttributes(qe);
554abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
55574077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            GrGLVertToFrag v(kVec4f_GrSLType);
55674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            args.fPB->addVarying("QuadEdge", &v);
5572dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName);
5582dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
5599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = args.fBT.cast<BatchTracker>();
5609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
5619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            // Setup pass through color
5629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
5639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                        &fColorUniform);
5649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
565abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // Setup position
566e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt            this->setupPosition(pb, gpArgs, qe.inPosition()->fName);
567abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
568abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt            // emit transforms
56946d36f0e7b709a077c647841eee23bd3efdc4117robertphillips            this->emitTransforms(args.fPB, gpArgs->fPositionVar, qe.inPosition()->fName,
570abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt                                 qe.localMatrix(), args.fTransformsIn, args.fTransformsOut);
57190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
57229bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel            GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
57330ba436f04e61d4505fb854d5fc56079636e0788joshualitt
57430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            SkAssertResult(fsBuilder->enableFeature(
57530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
57674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("float edgeAlpha;");
57730ba436f04e61d4505fb854d5fc56079636e0788joshualitt
57890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // keep the derivative instructions outside the conditional
57974077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
58074077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
58174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
58290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org            // today we know z and w are in device space. We could use derivatives
58374077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(),
58474077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                    v.fsIn());
58574077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf ("} else {");
58674077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("vec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,"
58774077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   "               2.0*%s.x*duvdy.x - duvdy.y);",
58874077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   v.fsIn(), v.fsIn());
58974077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
59074077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                    v.fsIn());
59174077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt            fsBuilder->codeAppendf("edgeAlpha = "
59274077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt                                   "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}");
59374077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt
5942dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt            fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
59590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org        }
59690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
5979b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        static inline void GenKey(const GrGeometryProcessor& gp,
5989b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                  const GrBatchTracker& bt,
599cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                  const GrGLSLCaps&,
6009b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                                  GrProcessorKeyBuilder* b) {
6019b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = bt.cast<BatchTracker>();
602e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt            const QuadEdgeEffect& qee = gp.cast<QuadEdgeEffect>();
60346d36f0e7b709a077c647841eee23bd3efdc4117robertphillips            uint32_t key = local.fInputColorType << 16;
604e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt            key |= local.fUsesLocalCoords && qee.localMatrix().hasPerspective() ? 0x1 : 0x0;
60546d36f0e7b709a077c647841eee23bd3efdc4117robertphillips            b->add32(key);
6069b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
60790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6089b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        virtual void setData(const GrGLProgramDataManager& pdman,
6099b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                             const GrPrimitiveProcessor& gp,
61036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                             const GrBatchTracker& bt) override {
6119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            const BatchTracker& local = bt.cast<BatchTracker>();
6129b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
6139b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                GrGLfloat c[4];
6149b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                GrColorToRGBAFloat(local.fColor, c);
6159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                pdman.set4fv(fColorUniform, 1, c);
6169b98932adaceb7ad0a617ade16616923f6bffe84joshualitt                fColor = local.fColor;
6179b98932adaceb7ad0a617ade16616923f6bffe84joshualitt            }
6189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        }
61990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
620e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt        void setTransformData(const GrPrimitiveProcessor& primProc,
621e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt                              const GrGLProgramDataManager& pdman,
622e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt                              int index,
623e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt                              const SkTArray<const GrCoordTransform*, true>& transforms) override {
624e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt            this->setTransformDataHelper<QuadEdgeEffect>(primProc, pdman, index, transforms);
625e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt        }
626e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt
62790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    private:
6289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrColor fColor;
6299b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        UniformHandle fColorUniform;
6309b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
631249af15fb82833d2274850c589812b6e69df0033joshualitt        typedef GrGLGeometryProcessor INHERITED;
63290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    };
633041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com
634eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    virtual void getGLProcessorKey(const GrBatchTracker& bt,
635cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                   const GrGLSLCaps& caps,
63636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                                   GrProcessorKeyBuilder* b) const override {
637eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        GLProcessor::GenKey(*this, bt, caps, b);
638eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    }
639eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
640abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
641cfc18867d982119d9dc2888bf09f1093012daaddjvanverth                                                     const GrGLSLCaps&) const override {
642eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        return SkNEW_ARGS(GLProcessor, (*this, bt));
643eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    }
644eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
64536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const override {
6469b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        BatchTracker* local = bt->cast<BatchTracker>();
6479b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
648290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        local->fUsesLocalCoords = init.fUsesLocalCoords;
6499b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    }
6509b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
65190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate:
652d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt    QuadEdgeEffect(GrColor color, const SkMatrix& localMatrix)
653e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt        : fColor(color)
654e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt        , fLocalMatrix(localMatrix) {
655eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        this->initClassID<QuadEdgeEffect>();
65671c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
65771c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt        fInQuadEdge = &this->addVertexAttrib(Attribute("inQuadEdge", kVec4f_GrVertexAttribType));
65890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    }
65990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    struct BatchTracker {
6619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrGPInput fInputColorType;
6629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt        GrColor fColor;
663290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        bool fUsesLocalCoords;
6649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt    };
6659b98932adaceb7ad0a617ade16616923f6bffe84joshualitt
66671c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* fInPosition;
66771c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt    const Attribute* fInQuadEdge;
66888c23fc6e8ed0243159fd17d815b4f813805647bjoshualitt    GrColor          fColor;
669e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt    SkMatrix         fLocalMatrix;
670249af15fb82833d2274850c589812b6e69df0033joshualitt
671b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
67290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6732e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt    typedef GrGeometryProcessor INHERITED;
67490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org};
67590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
676b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect);
67790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
678b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random,
679b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                GrContext*,
680b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                const GrDrawTargetCaps& caps,
681b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                GrTexture*[]) {
68290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org    // Doesn't work without derivative instructions.
683e9c0fc616d2a1632c285885b9b656b68ca8d4f24jvanverth    return caps.shaderCaps()->shaderDerivativeSupport() ?
684d27f73ef27ff65a6a0a5d00aa8e5b784b1a0b47ejoshualitt           QuadEdgeEffect::Create(GrRandomColor(random),
6854eaf9cef5a76098f78efac30beb966ac833d32c2joshualitt                                  GrTest::TestMatrix(random)) : NULL;
68690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}
68790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
68890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
68990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org
6909853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target,
6918dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel                                         const GrPipelineBuilder*,
6928059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt                                         const SkMatrix& viewMatrix,
6939853ccef19c200be93a6211f32589fa82a53067cjoshualitt                                         const SkPath& path,
6941899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                         const GrStrokeInfo& stroke,
6958a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com                                         bool antiAlias) const {
696e9c0fc616d2a1632c285885b9b656b68ca8d4f24jvanverth    return (target->caps()->shaderCaps()->shaderDerivativeSupport() && antiAlias &&
697e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com            stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
698c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com}
699c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
700e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips// extract the result vertices and indices from the GrAAConvexTessellator
701e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillipsstatic void extract_verts(const GrAAConvexTessellator& tess,
702e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                          void* vertices,
703e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                          size_t vertexStride,
704e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                          GrColor color,
705e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                          uint16_t* idxs,
706e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                          bool tweakAlphaForCoverage) {
707e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    intptr_t verts = reinterpret_cast<intptr_t>(vertices);
708e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
709e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    for (int i = 0; i < tess.numPts(); ++i) {
710e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i);
711e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    }
712e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
713e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    // Make 'verts' point to the colors
714e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    verts += sizeof(SkPoint);
715e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    for (int i = 0; i < tess.numPts(); ++i) {
716e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        SkASSERT(tess.depth(i) >= -0.5f && tess.depth(i) <= 0.5f);
717e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        if (tweakAlphaForCoverage) {
718e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            SkASSERT(SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f)) <= 255);
719e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            unsigned scale = SkScalarRoundToInt(255.0f * (tess.depth(i) + 0.5f));
720e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
721e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
722e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        } else {
723e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
724e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) =
725e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                                                                    tess.depth(i) + 0.5f;
726e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
727e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    }
728e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
729e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    for (int i = 0; i < tess.numIndices(); ++i) {
730e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        idxs[i] = tess.index(i);
731e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    }
732e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips}
733e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
734e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillipsstatic const GrGeometryProcessor* create_fill_gp(bool tweakAlphaForCoverage,
735e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                                                 const SkMatrix& localMatrix) {
736e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    uint32_t flags = GrDefaultGeoProcFactory::kColor_GPType;
737e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    if (!tweakAlphaForCoverage) {
738e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        flags |= GrDefaultGeoProcFactory::kCoverage_GPType;
739e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    }
740e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
7411ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt    return GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE, SkMatrix::I(), localMatrix);
742e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips}
743e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
74427f398f04dff306418a142c27175eaa35d21a915joshualittclass AAConvexPathBatch : public GrBatch {
74527f398f04dff306418a142c27175eaa35d21a915joshualittpublic:
74627f398f04dff306418a142c27175eaa35d21a915joshualitt    struct Geometry {
74727f398f04dff306418a142c27175eaa35d21a915joshualitt        GrColor fColor;
74827f398f04dff306418a142c27175eaa35d21a915joshualitt        SkMatrix fViewMatrix;
74927f398f04dff306418a142c27175eaa35d21a915joshualitt        SkPath fPath;
75027f398f04dff306418a142c27175eaa35d21a915joshualitt    };
751c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com
75227f398f04dff306418a142c27175eaa35d21a915joshualitt    static GrBatch* Create(const Geometry& geometry) {
75327f398f04dff306418a142c27175eaa35d21a915joshualitt        return SkNEW_ARGS(AAConvexPathBatch, (geometry));
75469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
7554647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
75636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "AAConvexBatch"; }
75769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
75836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
75927f398f04dff306418a142c27175eaa35d21a915joshualitt        // When this is called on a batch, there is only one geometry bundle
76027f398f04dff306418a142c27175eaa35d21a915joshualitt        out->setKnownFourComponents(fGeoData[0].fColor);
76127f398f04dff306418a142c27175eaa35d21a915joshualitt    }
76236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
76327f398f04dff306418a142c27175eaa35d21a915joshualitt        out->setUnknownSingleComponent();
764af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com    }
765af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
76636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void initBatchTracker(const GrPipelineInfo& init) override {
76727f398f04dff306418a142c27175eaa35d21a915joshualitt        // Handle any color overrides
76827f398f04dff306418a142c27175eaa35d21a915joshualitt        if (init.fColorIgnored) {
76927f398f04dff306418a142c27175eaa35d21a915joshualitt            fGeoData[0].fColor = GrColor_ILLEGAL;
77027f398f04dff306418a142c27175eaa35d21a915joshualitt        } else if (GrColor_ILLEGAL != init.fOverrideColor) {
77127f398f04dff306418a142c27175eaa35d21a915joshualitt            fGeoData[0].fColor = init.fOverrideColor;
77227f398f04dff306418a142c27175eaa35d21a915joshualitt        }
773af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com
77427f398f04dff306418a142c27175eaa35d21a915joshualitt        // setup batch properties
77527f398f04dff306418a142c27175eaa35d21a915joshualitt        fBatch.fColorIgnored = init.fColorIgnored;
77627f398f04dff306418a142c27175eaa35d21a915joshualitt        fBatch.fColor = fGeoData[0].fColor;
77727f398f04dff306418a142c27175eaa35d21a915joshualitt        fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
77827f398f04dff306418a142c27175eaa35d21a915joshualitt        fBatch.fCoverageIgnored = init.fCoverageIgnored;
779e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        fBatch.fLinesOnly = SkPath::kLine_SegmentMask == fGeoData[0].fPath.getSegmentMasks();
780e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        fBatch.fCanTweakAlphaForCoverage = init.fCanTweakAlphaForCoverage;
781e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    }
782e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
783e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    void generateGeometryLinesOnly(GrBatchTarget* batchTarget, const GrPipeline* pipeline) {
784e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
785e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
786e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        SkMatrix invert;
787e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
788e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            SkDebugf("Could not invert viewmatrix\n");
789e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            return;
790e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
791e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
792e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        // Setup GrGeometryProcessor
793e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        SkAutoTUnref<const GrGeometryProcessor> gp(
794e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                                                create_fill_gp(canTweakAlphaForCoverage, invert));
795e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
796e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        batchTarget->initDraw(gp, pipeline);
797e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
798e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        // TODO remove this when batch is everywhere
799e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        GrPipelineInfo init;
800e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        init.fColorIgnored = fBatch.fColorIgnored;
801e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        init.fOverrideColor = GrColor_ILLEGAL;
802e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        init.fCoverageIgnored = fBatch.fCoverageIgnored;
803e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        init.fUsesLocalCoords = this->usesLocalCoords();
804e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
805e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
806e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        size_t vertexStride = gp->getVertexStride();
807e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
808e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        SkASSERT(canTweakAlphaForCoverage ?
809e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
810e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
811e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
812e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        GrAAConvexTessellator tess;
813e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
814e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        int instanceCount = fGeoData.count();
815e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
816e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        for (int i = 0; i < instanceCount; i++) {
817e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            tess.rewind();
818e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
819e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            Geometry& args = fGeoData[i];
820e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
821e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
822e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                continue;
823e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            }
824e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
825e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            const GrVertexBuffer* vertexBuffer;
826e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            int firstVertex;
827e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
828e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            void* verts = batchTarget->makeVertSpace(vertexStride, tess.numPts(),
829e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                                                     &vertexBuffer, &firstVertex);
830e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            if (!verts) {
831e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                SkDebugf("Could not allocate vertices\n");
832e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                return;
833e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            }
834e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
835e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            const GrIndexBuffer* indexBuffer;
836e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            int firstIndex;
837e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
838e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            uint16_t* idxs = batchTarget->makeIndexSpace(tess.numIndices(),
839e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                                                        &indexBuffer, &firstIndex);
840e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            if (!idxs) {
841e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                SkDebugf("Could not allocate indices\n");
842e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                return;
843e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            }
844e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
845e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            extract_verts(tess, verts, vertexStride, args.fColor, idxs, canTweakAlphaForCoverage);
846e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
847e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            GrVertices info;
848e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            info.initIndexed(kTriangles_GrPrimitiveType,
849e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                             vertexBuffer, indexBuffer,
850e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                             firstVertex, firstIndex,
851e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips                             tess.numPts(), tess.numIndices());
852e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            batchTarget->draw(info);
853e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
85469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com    }
85569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
85636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
857e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips#ifndef SK_IGNORE_LINEONLY_AA_CONVEX_PATH_OPTS
858e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        if (this->linesOnly()) {
859e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            this->generateGeometryLinesOnly(batchTarget, pipeline);
860e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            return;
861e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
862e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips#endif
863e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
86427f398f04dff306418a142c27175eaa35d21a915joshualitt        int instanceCount = fGeoData.count();
865106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org
86627f398f04dff306418a142c27175eaa35d21a915joshualitt        SkMatrix invert;
8677abe15d7a905e9a0d70809ebabfaac201bfae6f0joshualitt        if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
86827f398f04dff306418a142c27175eaa35d21a915joshualitt            SkDebugf("Could not invert viewmatrix\n");
86927f398f04dff306418a142c27175eaa35d21a915joshualitt            return;
87027f398f04dff306418a142c27175eaa35d21a915joshualitt        }
8714647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com
87227f398f04dff306418a142c27175eaa35d21a915joshualitt        // Setup GrGeometryProcessor
87327f398f04dff306418a142c27175eaa35d21a915joshualitt        SkAutoTUnref<GrGeometryProcessor> quadProcessor(QuadEdgeEffect::Create(this->color(),
87427f398f04dff306418a142c27175eaa35d21a915joshualitt                                                                               invert));
87527f398f04dff306418a142c27175eaa35d21a915joshualitt
87627f398f04dff306418a142c27175eaa35d21a915joshualitt        batchTarget->initDraw(quadProcessor, pipeline);
87727f398f04dff306418a142c27175eaa35d21a915joshualitt
87827f398f04dff306418a142c27175eaa35d21a915joshualitt        // TODO remove this when batch is everywhere
87927f398f04dff306418a142c27175eaa35d21a915joshualitt        GrPipelineInfo init;
88027f398f04dff306418a142c27175eaa35d21a915joshualitt        init.fColorIgnored = fBatch.fColorIgnored;
88127f398f04dff306418a142c27175eaa35d21a915joshualitt        init.fOverrideColor = GrColor_ILLEGAL;
88227f398f04dff306418a142c27175eaa35d21a915joshualitt        init.fCoverageIgnored = fBatch.fCoverageIgnored;
88327f398f04dff306418a142c27175eaa35d21a915joshualitt        init.fUsesLocalCoords = this->usesLocalCoords();
88427f398f04dff306418a142c27175eaa35d21a915joshualitt        quadProcessor->initBatchTracker(batchTarget->currentBatchTracker(), init);
88527f398f04dff306418a142c27175eaa35d21a915joshualitt
88627f398f04dff306418a142c27175eaa35d21a915joshualitt        // TODO generate all segments for all paths and use one vertex buffer
88727f398f04dff306418a142c27175eaa35d21a915joshualitt        for (int i = 0; i < instanceCount; i++) {
88827f398f04dff306418a142c27175eaa35d21a915joshualitt            Geometry& args = fGeoData[i];
88927f398f04dff306418a142c27175eaa35d21a915joshualitt
89027f398f04dff306418a142c27175eaa35d21a915joshualitt            // We use the fact that SkPath::transform path does subdivision based on
89127f398f04dff306418a142c27175eaa35d21a915joshualitt            // perspective. Otherwise, we apply the view matrix when copying to the
89227f398f04dff306418a142c27175eaa35d21a915joshualitt            // segment representation.
89327f398f04dff306418a142c27175eaa35d21a915joshualitt            const SkMatrix* viewMatrix = &args.fViewMatrix;
89427f398f04dff306418a142c27175eaa35d21a915joshualitt            if (viewMatrix->hasPerspective()) {
89527f398f04dff306418a142c27175eaa35d21a915joshualitt                args.fPath.transform(*viewMatrix);
89627f398f04dff306418a142c27175eaa35d21a915joshualitt                viewMatrix = &SkMatrix::I();
89727f398f04dff306418a142c27175eaa35d21a915joshualitt            }
89827f398f04dff306418a142c27175eaa35d21a915joshualitt
89927f398f04dff306418a142c27175eaa35d21a915joshualitt            int vertexCount;
90027f398f04dff306418a142c27175eaa35d21a915joshualitt            int indexCount;
90127f398f04dff306418a142c27175eaa35d21a915joshualitt            enum {
90227f398f04dff306418a142c27175eaa35d21a915joshualitt                kPreallocSegmentCnt = 512 / sizeof(Segment),
90327f398f04dff306418a142c27175eaa35d21a915joshualitt                kPreallocDrawCnt = 4,
90427f398f04dff306418a142c27175eaa35d21a915joshualitt            };
90527f398f04dff306418a142c27175eaa35d21a915joshualitt            SkSTArray<kPreallocSegmentCnt, Segment, true> segments;
90627f398f04dff306418a142c27175eaa35d21a915joshualitt            SkPoint fanPt;
90727f398f04dff306418a142c27175eaa35d21a915joshualitt
90827f398f04dff306418a142c27175eaa35d21a915joshualitt            if (!get_segments(args.fPath, *viewMatrix, &segments, &fanPt, &vertexCount,
90927f398f04dff306418a142c27175eaa35d21a915joshualitt                              &indexCount)) {
91027f398f04dff306418a142c27175eaa35d21a915joshualitt                continue;
91127f398f04dff306418a142c27175eaa35d21a915joshualitt            }
91227f398f04dff306418a142c27175eaa35d21a915joshualitt
91327f398f04dff306418a142c27175eaa35d21a915joshualitt            const GrVertexBuffer* vertexBuffer;
91427f398f04dff306418a142c27175eaa35d21a915joshualitt            int firstVertex;
91527f398f04dff306418a142c27175eaa35d21a915joshualitt
91627f398f04dff306418a142c27175eaa35d21a915joshualitt            size_t vertexStride = quadProcessor->getVertexStride();
917e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon            QuadVertex* verts = reinterpret_cast<QuadVertex*>(batchTarget->makeVertSpace(
918e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon                vertexStride, vertexCount, &vertexBuffer, &firstVertex));
919e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon
920e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon            if (!verts) {
9214b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt                SkDebugf("Could not allocate vertices\n");
9224b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt                return;
9234b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            }
9244b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt
92527f398f04dff306418a142c27175eaa35d21a915joshualitt            const GrIndexBuffer* indexBuffer;
92627f398f04dff306418a142c27175eaa35d21a915joshualitt            int firstIndex;
92727f398f04dff306418a142c27175eaa35d21a915joshualitt
928e40d39725908d99d255496025411e5c9ca32663erobertphillips            uint16_t *idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
929e40d39725908d99d255496025411e5c9ca32663erobertphillips            if (!idxs) {
9304b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt                SkDebugf("Could not allocate indices\n");
9314b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt                return;
9324b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt            }
9334b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt
93427f398f04dff306418a142c27175eaa35d21a915joshualitt            SkSTArray<kPreallocDrawCnt, Draw, true> draws;
93527f398f04dff306418a142c27175eaa35d21a915joshualitt            create_vertices(segments, fanPt, &draws, verts, idxs);
9367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com
937e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon            GrVertices vertices;
93827f398f04dff306418a142c27175eaa35d21a915joshualitt
93927f398f04dff306418a142c27175eaa35d21a915joshualitt            for (int i = 0; i < draws.count(); ++i) {
94027f398f04dff306418a142c27175eaa35d21a915joshualitt                const Draw& draw = draws[i];
941e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon                vertices.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
942e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon                                     firstVertex, firstIndex, draw.fVertexCnt, draw.fIndexCnt);
943e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon                batchTarget->draw(vertices);
944b5238a7571c243ba4a154a62575570c3078b3741bsalomon                firstVertex += draw.fVertexCnt;
945b5238a7571c243ba4a154a62575570c3078b3741bsalomon                firstIndex += draw.fIndexCnt;
94627f398f04dff306418a142c27175eaa35d21a915joshualitt            }
94727f398f04dff306418a142c27175eaa35d21a915joshualitt        }
94827f398f04dff306418a142c27175eaa35d21a915joshualitt    }
94927f398f04dff306418a142c27175eaa35d21a915joshualitt
95027f398f04dff306418a142c27175eaa35d21a915joshualitt    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
95127f398f04dff306418a142c27175eaa35d21a915joshualitt
95227f398f04dff306418a142c27175eaa35d21a915joshualittprivate:
95327f398f04dff306418a142c27175eaa35d21a915joshualitt    AAConvexPathBatch(const Geometry& geometry) {
95427f398f04dff306418a142c27175eaa35d21a915joshualitt        this->initClassID<AAConvexPathBatch>();
95527f398f04dff306418a142c27175eaa35d21a915joshualitt        fGeoData.push_back(geometry);
95699c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
95799c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        // compute bounds
95899c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        fBounds = geometry.fPath.getBounds();
95999c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        geometry.fViewMatrix.mapRect(&fBounds);
96027f398f04dff306418a142c27175eaa35d21a915joshualitt    }
96127f398f04dff306418a142c27175eaa35d21a915joshualitt
96236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onCombineIfPossible(GrBatch* t) override {
96327f398f04dff306418a142c27175eaa35d21a915joshualitt        AAConvexPathBatch* that = t->cast<AAConvexPathBatch>();
96427f398f04dff306418a142c27175eaa35d21a915joshualitt
96527f398f04dff306418a142c27175eaa35d21a915joshualitt        if (this->color() != that->color()) {
96627f398f04dff306418a142c27175eaa35d21a915joshualitt            return false;
96727f398f04dff306418a142c27175eaa35d21a915joshualitt        }
96827f398f04dff306418a142c27175eaa35d21a915joshualitt
96927f398f04dff306418a142c27175eaa35d21a915joshualitt        SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
97027f398f04dff306418a142c27175eaa35d21a915joshualitt        if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
97127f398f04dff306418a142c27175eaa35d21a915joshualitt            return false;
97227f398f04dff306418a142c27175eaa35d21a915joshualitt        }
97327f398f04dff306418a142c27175eaa35d21a915joshualitt
974e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        if (this->linesOnly() != that->linesOnly()) {
975e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            return false;
976e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
977e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
978e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        // In the event of two batches, one who can tweak, one who cannot, we just fall back to
979e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        // not tweaking
980e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) {
981e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips            fBatch.fCanTweakAlphaForCoverage = false;
982e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        }
983e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips
98427f398f04dff306418a142c27175eaa35d21a915joshualitt        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
98599c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        this->joinBounds(that->bounds());
98627f398f04dff306418a142c27175eaa35d21a915joshualitt        return true;
98727f398f04dff306418a142c27175eaa35d21a915joshualitt    }
98827f398f04dff306418a142c27175eaa35d21a915joshualitt
98927f398f04dff306418a142c27175eaa35d21a915joshualitt    GrColor color() const { return fBatch.fColor; }
990e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    bool linesOnly() const { return fBatch.fLinesOnly; }
99127f398f04dff306418a142c27175eaa35d21a915joshualitt    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
992e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips    bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
99327f398f04dff306418a142c27175eaa35d21a915joshualitt    const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
99427f398f04dff306418a142c27175eaa35d21a915joshualitt
99527f398f04dff306418a142c27175eaa35d21a915joshualitt    struct BatchTracker {
99627f398f04dff306418a142c27175eaa35d21a915joshualitt        GrColor fColor;
99727f398f04dff306418a142c27175eaa35d21a915joshualitt        bool fUsesLocalCoords;
99827f398f04dff306418a142c27175eaa35d21a915joshualitt        bool fColorIgnored;
99927f398f04dff306418a142c27175eaa35d21a915joshualitt        bool fCoverageIgnored;
1000e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        bool fLinesOnly;
1001e16dfdbeadcb659e2ff4c56669fc08ee69e3f18frobertphillips        bool fCanTweakAlphaForCoverage;
100227f398f04dff306418a142c27175eaa35d21a915joshualitt    };
100327f398f04dff306418a142c27175eaa35d21a915joshualitt
100427f398f04dff306418a142c27175eaa35d21a915joshualitt    BatchTracker fBatch;
100527f398f04dff306418a142c27175eaa35d21a915joshualitt    SkSTArray<1, Geometry, true> fGeoData;
100627f398f04dff306418a142c27175eaa35d21a915joshualitt};
100727f398f04dff306418a142c27175eaa35d21a915joshualitt
100827f398f04dff306418a142c27175eaa35d21a915joshualittbool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target,
100927f398f04dff306418a142c27175eaa35d21a915joshualitt                                        GrPipelineBuilder* pipelineBuilder,
101027f398f04dff306418a142c27175eaa35d21a915joshualitt                                        GrColor color,
101127f398f04dff306418a142c27175eaa35d21a915joshualitt                                        const SkMatrix& vm,
101227f398f04dff306418a142c27175eaa35d21a915joshualitt                                        const SkPath& path,
10131899651ffc459f5462aa989cd6d08507947b67e4kkinnunen                                        const GrStrokeInfo&,
101427f398f04dff306418a142c27175eaa35d21a915joshualitt                                        bool antiAlias) {
101527f398f04dff306418a142c27175eaa35d21a915joshualitt    if (path.isEmpty()) {
101627f398f04dff306418a142c27175eaa35d21a915joshualitt        return true;
10177d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com    }
1018a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
101927f398f04dff306418a142c27175eaa35d21a915joshualitt    AAConvexPathBatch::Geometry geometry;
102027f398f04dff306418a142c27175eaa35d21a915joshualitt    geometry.fColor = color;
102127f398f04dff306418a142c27175eaa35d21a915joshualitt    geometry.fViewMatrix = vm;
102227f398f04dff306418a142c27175eaa35d21a915joshualitt    geometry.fPath = path;
102327f398f04dff306418a142c27175eaa35d21a915joshualitt
102427f398f04dff306418a142c27175eaa35d21a915joshualitt    SkAutoTUnref<GrBatch> batch(AAConvexPathBatch::Create(geometry));
102599c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    target->drawBatch(pipelineBuilder, batch);
102627f398f04dff306418a142c27175eaa35d21a915joshualitt
1027c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com    return true;
102827f398f04dff306418a142c27175eaa35d21a915joshualitt
102969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}
10308e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt
10318e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt///////////////////////////////////////////////////////////////////////////////////////////////////
10328e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt
10338e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt#ifdef GR_TEST_UTILS
10348e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt
10356c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualittBATCH_TEST_DEFINE(AAConvexPathBatch) {
10368e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt    AAConvexPathBatch::Geometry geometry;
10378e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt    geometry.fColor = GrRandomColor(random);
10386c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt    geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
10398e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt    geometry.fPath = GrTest::TestPathConvex(random);
10408e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt
10418e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt    return AAConvexPathBatch::Create(geometry);
10428e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt}
10438e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt
10448e5c177c8589e00f630ac6fae763c65cb9cae896joshualitt#endif
1045