1fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
2fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/*
3fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth * Copyright 2014 Google Inc.
4fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth *
5fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth * Use of this source code is governed by a BSD-style license that can be
6fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth * found in the LICENSE file.
7fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth */
8fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
9fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "GrAADistanceFieldPathRenderer.h"
10fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
117539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon#include "GrBatchFlushState.h"
1221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt#include "GrBatchTest.h"
13fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "GrContext.h"
148dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel#include "GrPipelineBuilder.h"
15b5238a7571c243ba4a154a62575570c3078b3741bsalomon#include "GrResourceProvider.h"
16fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "GrSurfacePriv.h"
17fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "GrSWMaskHelper.h"
18fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "GrTexturePriv.h"
1972e3ae486c66871c2043eac4f08d85d419fbca2absalomon#include "GrVertexBuffer.h"
2016b991390bb988b194a868ab8de66db4c21c7c13bsalomon#include "batches/GrVertexBatch.h"
218ed3b9a386374d7996dfbe0c9de13b42f3dd245djvanverth#include "effects/GrDistanceFieldGeoProc.h"
22fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
23fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "SkDistanceFieldGen.h"
24fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#include "SkRTConf.h"
25fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
26fb1e2fc8aa25b8c2ef0714c27cfcb1ee0f8f806bjvanverth#define ATLAS_TEXTURE_WIDTH 2048
27b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth#define ATLAS_TEXTURE_HEIGHT 2048
28fb1e2fc8aa25b8c2ef0714c27cfcb1ee0f8f806bjvanverth#define PLOT_WIDTH  512
29e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed#define PLOT_HEIGHT 256
30fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
31fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#define NUM_PLOTS_X   (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH)
32fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth#define NUM_PLOTS_Y   (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT)
33fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
34b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#ifdef DF_PATH_TRACKING
35b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverthstatic int g_NumCachedPaths = 0;
36b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverthstatic int g_NumFreedPaths = 0;
37b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#endif
38b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth
39b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth// mip levels
40b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverthstatic const int kSmallMIP = 32;
41512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverthstatic const int kMediumMIP = 73;
42fb1e2fc8aa25b8c2ef0714c27cfcb1ee0f8f806bjvanverthstatic const int kLargeMIP = 162;
43b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth
445bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt// Callback to clear out internal path cache when eviction occurs
455bf99f1ca8f30287803b594d06c60a7b6796ad45joshualittvoid GrAADistanceFieldPathRenderer::HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
465bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    GrAADistanceFieldPathRenderer* dfpr = (GrAADistanceFieldPathRenderer*)pr;
475bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    // remove any paths that use this plot
485bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    PathDataList::Iter iter;
495bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart);
505bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    PathData* pathData;
515bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    while ((pathData = iter.get())) {
525bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        iter.next();
535bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        if (id == pathData->fID) {
545bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            dfpr->fPathCache.remove(pathData->fKey);
555bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            dfpr->fPathList.remove(pathData);
56385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete pathData;
575bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt#ifdef DF_PATH_TRACKING
585bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            ++g_NumFreedPaths;
595bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt#endif
605bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        }
615bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
625bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt}
635bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
64fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth////////////////////////////////////////////////////////////////////////////////
6596fcdcc219d2a0d3579719b84b28bede76efba64halcanaryGrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer() : fAtlas(nullptr) {}
666d22ecaa71cf4400feebc3438bf0e0dd68179500jvanverth
67fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthGrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
68fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    PathDataList::Iter iter;
69fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
70fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    PathData* pathData;
71fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    while ((pathData = iter.get())) {
72fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        iter.next();
73fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        fPathList.remove(pathData);
74385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete pathData;
75fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
76385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fAtlas;
77b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth
78b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#ifdef DF_PATH_TRACKING
79b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    SkDebugf("Cached paths: %d, freed paths: %d\n", g_NumCachedPaths, g_NumFreedPaths);
80b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#endif
81fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
82fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
83fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth////////////////////////////////////////////////////////////////////////////////
840aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
85fb1e2fc8aa25b8c2ef0714c27cfcb1ee0f8f806bjvanverth
86fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    // TODO: Support inverse fill
87e7d4b2f5dc3c35f351ba120018c214f739447fb2robertphillips    if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias ||
88512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        SkStrokeRec::kHairline_Style == args.fStroke->getStyle() ||
89dde87ad6d5278661aac6a8eda9e8f43deb255fe2fmalita        args.fPath->isInverseFillType() || args.fPath->isVolatile() ||
90dde87ad6d5278661aac6a8eda9e8f43deb255fe2fmalita        // We don't currently apply the dash or factor it into the DF key. (skbug.com/5082)
91dde87ad6d5278661aac6a8eda9e8f43deb255fe2fmalita        args.fStroke->isDashed()) {
92fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        return false;
93fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
94fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
95b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth    // currently don't support perspective
960aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    if (args.fViewMatrix->hasPerspective()) {
97fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        return false;
98fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
99fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
100512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // only support paths with bounds within kMediumMIP by kMediumMIP,
101512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP
102b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth    // the goal is to accelerate rendering of lots of small paths that may be scaling
1030aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    SkScalar maxScale = args.fViewMatrix->getMaxScale();
1040aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    const SkRect& bounds = args.fPath->getBounds();
105b61283f9c7cbec4236d6ce6ce9d0376d3dd81207jvanverth    SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
106512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // Approximate stroked size by adding the maximum of the stroke width or 2x the miter limit
107512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    if (!args.fStroke->isFillStyle()) {
108512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        SkScalar extraWidth = args.fStroke->getWidth();
109512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        if (SkPaint::kMiter_Join == args.fStroke->getJoin()) {
110512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth            extraWidth = SkTMax(extraWidth, 2.0f*args.fStroke->getMiter());
111512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        }
112512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        maxDim += extraWidth;
113512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    }
114dde87ad6d5278661aac6a8eda9e8f43deb255fe2fmalita
115512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP;
116fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
117fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
118fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth////////////////////////////////////////////////////////////////////////////////
119fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
1205bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt// padding around path bounds to allow for antialiased pixels
1215bf99f1ca8f30287803b594d06c60a7b6796ad45joshualittstatic const SkScalar kAntiAliasPad = 1.0f;
1225bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
123abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonclass AADistanceFieldPathBatch : public GrVertexBatch {
1245bf99f1ca8f30287803b594d06c60a7b6796ad45joshualittpublic:
1251b55a963a2374a14bb82eb887bb99ee91680f0ebreed    DEFINE_BATCH_CLASS_ID
1261b55a963a2374a14bb82eb887bb99ee91680f0ebreed
1275bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    typedef GrAADistanceFieldPathRenderer::PathData PathData;
1285bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    typedef SkTDynamicHash<PathData, PathData::Key> PathCache;
1295bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
1305bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
1315bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    struct Geometry {
132512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        Geometry(const SkStrokeRec& stroke) : fStroke(stroke) {
133512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth            if (!stroke.needToApply()) {
134512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                // purify unused values to ensure binary equality
135512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                fStroke.setStrokeParams(SkPaint::kDefault_Cap, SkPaint::kDefault_Join,
136512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                                        SkIntToScalar(4));
137512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                if (fStroke.getWidth() < 0) {
138512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                    fStroke.setStrokeStyle(-1.0f);
139512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                }
140512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth            }
141512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        }
1425bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkPath fPath;
143512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        // The unique ID of the path involved in this draw. This may be different than the ID
144512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        // in fPath since that path may have resulted from a SkStrokeRec::applyToPath call.
145512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        uint32_t fGenID;
1465bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkStrokeRec fStroke;
14753f26aa045d58feb9f2114f53629024bffe52deajoshualitt        GrColor fColor;
1485bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        bool fAntiAlias;
1495bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    };
1505bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
15153f26aa045d58feb9f2114f53629024bffe52deajoshualitt    static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
152abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                               GrBatchAtlas* atlas, PathCache* pathCache, PathDataList* pathList) {
15353f26aa045d58feb9f2114f53629024bffe52deajoshualitt        return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCache, pathList);
154fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
155fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
15636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "AADistanceFieldPathBatch"; }
157fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
158ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas    void computePipelineOptimizations(GrInitInvariantOutput* color,
159ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                                      GrInitInvariantOutput* coverage,
160ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas                                      GrBatchToXPOverrides* overrides) const override {
16153f26aa045d58feb9f2114f53629024bffe52deajoshualitt        color->setKnownFourComponents(fGeoData[0].fColor);
162ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        coverage->setUnknownSingleComponent();
1635bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
1645bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
165e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate:
166ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
1675bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // Handle any color overrides
168ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        if (!overrides.readsColor()) {
16953f26aa045d58feb9f2114f53629024bffe52deajoshualitt            fGeoData[0].fColor = GrColor_ILLEGAL;
170fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
17153f26aa045d58feb9f2114f53629024bffe52deajoshualitt        overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1725bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
1735bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // setup batch properties
174ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        fBatch.fColorIgnored = !overrides.readsColor();
175ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
176ff2103200bad7abcf8929ae22ac78a9f4f725142ethannicholas        fBatch.fCoverageIgnored = !overrides.readsCoverage();
177fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
178fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
179b5238a7571c243ba4a154a62575570c3078b3741bsalomon    struct FlushInfo {
180b5238a7571c243ba4a154a62575570c3078b3741bsalomon        SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
181b5238a7571c243ba4a154a62575570c3078b3741bsalomon        SkAutoTUnref<const GrIndexBuffer>  fIndexBuffer;
182b5238a7571c243ba4a154a62575570c3078b3741bsalomon        int fVertexOffset;
183b5238a7571c243ba4a154a62575570c3078b3741bsalomon        int fInstancesToFlush;
184b5238a7571c243ba4a154a62575570c3078b3741bsalomon    };
185b5238a7571c243ba4a154a62575570c3078b3741bsalomon
186144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt    void onPrepareDraws(Target* target) const override {
1875bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        int instanceCount = fGeoData.count();
188fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
1895bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkMatrix invert;
1905bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
1915bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkDebugf("Could not invert viewmatrix\n");
1925bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            return;
1939491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt        }
1949491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt
1955bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        uint32_t flags = 0;
1965bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        flags |= this->viewMatrix().isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
1975bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
1985bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
1995bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2005bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // Setup GrGeometryProcessor
2015bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        GrBatchAtlas* atlas = fAtlas;
2025bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkAutoTUnref<GrGeometryProcessor> dfProcessor(
203502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                GrDistanceFieldPathGeoProc::Create(this->color(),
204502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   this->viewMatrix(),
205502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   atlas->getTexture(),
206502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth                                                   params,
207b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt                                                   flags,
208b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt                                                   this->usesLocalCoords()));
2095bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2107539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        target->initDraw(dfProcessor, this->pipeline());
2115bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
212b5238a7571c243ba4a154a62575570c3078b3741bsalomon        FlushInfo flushInfo;
213ed0bcad9c8147fd37c23bdda00ec27ec9ef8d66bbsalomon
2145bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // allocate vertices
2155bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        size_t vertexStride = dfProcessor->getVertexStride();
21653f26aa045d58feb9f2114f53629024bffe52deajoshualitt        SkASSERT(vertexStride == 2 * sizeof(SkPoint) + sizeof(GrColor));
2178415abe44cf205ac214b7793c076fd8c13272240bsalomon
218b5238a7571c243ba4a154a62575570c3078b3741bsalomon        const GrVertexBuffer* vertexBuffer;
2197539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        void* vertices = target->makeVertexSpace(vertexStride,
2207539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon                                                 kVerticesPerQuad * instanceCount,
2217539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon                                                 &vertexBuffer,
2227539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon                                                 &flushInfo.fVertexOffset);
223b5238a7571c243ba4a154a62575570c3078b3741bsalomon        flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
2247539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuffer());
225b5238a7571c243ba4a154a62575570c3078b3741bsalomon        if (!vertices || !flushInfo.fIndexBuffer) {
2265bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkDebugf("Could not allocate vertices\n");
2275bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            return;
2289491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt        }
2299491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt
230b5238a7571c243ba4a154a62575570c3078b3741bsalomon        flushInfo.fInstancesToFlush = 0;
2315bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        for (int i = 0; i < instanceCount; i++) {
232144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt            const Geometry& args = fGeoData[i];
2335bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2345bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            // get mip level
2355bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkScalar maxScale = this->viewMatrix().getMaxScale();
2365bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            const SkRect& bounds = args.fPath.getBounds();
2375bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
2385bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkScalar size = maxScale * maxDim;
2395bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            uint32_t desiredDimension;
2405bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            if (size <= kSmallMIP) {
2415bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                desiredDimension = kSmallMIP;
2425bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            } else if (size <= kMediumMIP) {
2435bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                desiredDimension = kMediumMIP;
2445bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            } else {
2455bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                desiredDimension = kLargeMIP;
2465bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            }
2479491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt
2485bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            // check to see if path is cached
249512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth            PathData::Key key(args.fGenID, desiredDimension, args.fStroke);
250144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt            PathData* pathData = fPathCache->find(key);
251144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt            if (nullptr == pathData || !atlas->hasID(pathData->fID)) {
2525bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                // Remove the stale cache entry
253144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                if (pathData) {
254144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                    fPathCache->remove(pathData->fKey);
255144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                    fPathList->remove(pathData);
256144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                    delete pathData;
2575bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                }
2585bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                SkScalar scale = desiredDimension/maxDim;
259144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                pathData = new PathData;
2607539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon                if (!this->addPathToAtlas(target,
2615bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          dfProcessor,
262fb1141ae1db2ffce479bc46413b008d31cf9d3ccbsalomon                                          this->pipeline(),
263b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                          &flushInfo,
2645bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          atlas,
265144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                                          pathData,
2665bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          args.fPath,
267512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                                          args.fGenID,
2685bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          args.fStroke,
2695bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          args.fAntiAlias,
2705bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          desiredDimension,
2715bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                          scale)) {
2725bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                    SkDebugf("Can't rasterize path\n");
2735bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                    return;
2745bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                }
2759491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt            }
2769491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt
277144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt            atlas->setLastUseToken(pathData->fID, target->currentToken());
2785bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2795bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            // Now set vertices
2805bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            intptr_t offset = reinterpret_cast<intptr_t>(vertices);
281b5238a7571c243ba4a154a62575570c3078b3741bsalomon            offset += i * kVerticesPerQuad * vertexStride;
2827539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon            this->writePathVertices(target,
283b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                    atlas,
284fb1141ae1db2ffce479bc46413b008d31cf9d3ccbsalomon                                    this->pipeline(),
285b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                    dfProcessor,
28653f26aa045d58feb9f2114f53629024bffe52deajoshualitt                                    offset,
28753f26aa045d58feb9f2114f53629024bffe52deajoshualitt                                    args.fColor,
288b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                    vertexStride,
289b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                    this->viewMatrix(),
290b5238a7571c243ba4a154a62575570c3078b3741bsalomon                                    args.fPath,
291144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                                    pathData);
292b5238a7571c243ba4a154a62575570c3078b3741bsalomon            flushInfo.fInstancesToFlush++;
293fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
2945bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2957539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        this->flush(target, &flushInfo);
296fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
2975bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
2985bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
2995bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
30053f26aa045d58feb9f2114f53629024bffe52deajoshualitt    AADistanceFieldPathBatch(const Geometry& geometry,
30153f26aa045d58feb9f2114f53629024bffe52deajoshualitt                             const SkMatrix& viewMatrix,
3025bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                             GrBatchAtlas* atlas,
3031b55a963a2374a14bb82eb887bb99ee91680f0ebreed                             PathCache* pathCache, PathDataList* pathList)
3041b55a963a2374a14bb82eb887bb99ee91680f0ebreed        : INHERITED(ClassID()) {
3055bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fBatch.fViewMatrix = viewMatrix;
3065bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fGeoData.push_back(geometry);
3075bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3085bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fAtlas = atlas;
3095bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fPathCache = pathCache;
3105bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fPathList = pathList;
31199c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
31299c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        // Compute bounds
31399c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        fBounds = geometry.fPath.getBounds();
31499c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        viewMatrix.mapRect(&fBounds);
315fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
3169491f7ff319b0440a0e293f7d97240207f27dbdfjoshualitt
3177539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon    bool addPathToAtlas(GrVertexBatch::Target* target,
3185bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        const GrGeometryProcessor* dfProcessor,
3195bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        const GrPipeline* pipeline,
320b5238a7571c243ba4a154a62575570c3078b3741bsalomon                        FlushInfo* flushInfo,
3215bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        GrBatchAtlas* atlas,
3225bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        PathData* pathData,
3235bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        const SkPath& path,
324512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                        uint32_t genID,
325512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                        const SkStrokeRec& stroke,
326512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                        bool antiAlias,
3275bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                        uint32_t dimension,
328144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                        SkScalar scale) const {
3295bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        const SkRect& bounds = path.getBounds();
3305bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3315bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // generate bounding rect for bitmap draw
3325bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkRect scaledBounds = bounds;
3335bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // scale to mip level size
3345bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fLeft *= scale;
3355bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fTop *= scale;
3365bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fRight *= scale;
3375bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fBottom *= scale;
3385bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // move the origin to an integer boundary (gives better results)
3395bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
3405bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar dy = SkScalarFraction(scaledBounds.fTop);
3415bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.offset(-dx, -dy);
3425bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // get integer boundary
3435bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkIRect devPathBounds;
3445bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.roundOut(&devPathBounds);
3455bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // pad to allow room for antialiasing
346ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        const int intPad = SkScalarCeilToInt(kAntiAliasPad);
347ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        // pre-move origin (after outset, will be 0,0)
348ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        int width = devPathBounds.width();
349ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        int height = devPathBounds.height();
350ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        devPathBounds.fLeft = intPad;
351ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        devPathBounds.fTop = intPad;
352ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        devPathBounds.fRight = intPad + width;
353ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        devPathBounds.fBottom = intPad + height;
354ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        devPathBounds.outset(intPad, intPad);
3555bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3565bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // draw path to bitmap
3575bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkMatrix drawMatrix;
3585bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        drawMatrix.setTranslate(-bounds.left(), -bounds.top());
3595bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        drawMatrix.postScale(scale, scale);
3605bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
3615bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3625bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // setup bitmap backing
363512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        SkASSERT(devPathBounds.fLeft == 0);
364512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        SkASSERT(devPathBounds.fTop == 0);
36541e010cb901c0da9066c4df562030808c9ccd7f8reed        SkAutoPixmapStorage dst;
366512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        if (!dst.tryAlloc(SkImageInfo::MakeA8(devPathBounds.width(),
367512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth                                              devPathBounds.height()))) {
3685bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            return false;
3695bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        }
37041e010cb901c0da9066c4df562030808c9ccd7f8reed        sk_bzero(dst.writable_addr(), dst.getSafeSize());
3715bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3725bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // rasterize path
3735bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkPaint paint;
374512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        paint.setStyle(SkPaint::kFill_Style);
3755bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        paint.setAntiAlias(antiAlias);
3765bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3775bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkDraw draw;
3785bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        sk_bzero(&draw, sizeof(draw));
3795bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3805bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkRasterClip rasterClip;
381512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        rasterClip.setRect(devPathBounds);
3825bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        draw.fRC = &rasterClip;
3835bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        draw.fClip = &rasterClip.bwRgn();
3845bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        draw.fMatrix = &drawMatrix;
38541e010cb901c0da9066c4df562030808c9ccd7f8reed        draw.fDst = dst;
3865bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3875bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        draw.drawPathCoverage(path, paint);
3885bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3895bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // generate signed distance field
3905bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
391ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        width = devPathBounds.width();
392ecbed9d01bdb7906e4a85bebd3e5b6b23fbacedfjvanverth        height = devPathBounds.height();
3935bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // TODO We should really generate this directly into the plot somehow
3945bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char));
3955bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
3965bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // Generate signed distance field
39741e010cb901c0da9066c4df562030808c9ccd7f8reed        SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(),
39841e010cb901c0da9066c4df562030808c9ccd7f8reed                                           (const unsigned char*)dst.addr(),
39941e010cb901c0da9066c4df562030808c9ccd7f8reed                                           dst.width(), dst.height(), dst.rowBytes());
4005bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4015bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // add to atlas
4025bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkIPoint16 atlasLocation;
4035bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        GrBatchAtlas::AtlasID id;
4047539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.get(),
4055bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                         &atlasLocation);
4065bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        if (!success) {
4077539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon            this->flush(target, flushInfo);
4087539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon            target->initDraw(dfProcessor, pipeline);
4095bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4107539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon            SkDEBUGCODE(success =) atlas->addToAtlas(&id, target, width, height,
4115bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                                     dfStorage.get(), &atlasLocation);
4125bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkASSERT(success);
4135bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4145bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        }
4155bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4165bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // add to cache
417512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        pathData->fKey = PathData::Key(genID, dimension, stroke);
4185bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        pathData->fScale = scale;
4195bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        pathData->fID = id;
4205bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // change the scaled rect to match the size of the inset distance field
4215bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fRight = scaledBounds.fLeft +
4225bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
4235bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.fBottom = scaledBounds.fTop +
4245bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
4255bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // shift the origin to the correct place relative to the distance field
4265bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // need to also restore the fractional translation
4275bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx,
4285bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                            -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy);
4295bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        pathData->fBounds = scaledBounds;
4305bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // origin we render from is inset from distance field edge
4315bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        atlasLocation.fX += SK_DistanceFieldInset;
4325bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        atlasLocation.fY += SK_DistanceFieldInset;
4335bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        pathData->fAtlasLocation = atlasLocation;
4345bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4355bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fPathCache->add(pathData);
4365bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fPathList->addToTail(pathData);
437b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#ifdef DF_PATH_TRACKING
4385bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        ++g_NumCachedPaths;
439b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth#endif
4405bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        return true;
4415bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
442b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth
4437539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon    void writePathVertices(GrDrawBatch::Target* target,
444b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           GrBatchAtlas* atlas,
445b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           const GrPipeline* pipeline,
446b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           const GrGeometryProcessor* gp,
44753f26aa045d58feb9f2114f53629024bffe52deajoshualitt                           intptr_t offset,
44853f26aa045d58feb9f2114f53629024bffe52deajoshualitt                           GrColor color,
449b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           size_t vertexStride,
450b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           const SkMatrix& viewMatrix,
451b5238a7571c243ba4a154a62575570c3078b3741bsalomon                           const SkPath& path,
452144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt                           const PathData* pathData) const {
4535bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        GrTexture* texture = atlas->getTexture();
4545bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4555bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar dx = pathData->fBounds.fLeft;
4565bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar dy = pathData->fBounds.fTop;
4575bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar width = pathData->fBounds.width();
4585bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar height = pathData->fBounds.height();
4595bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
4605bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkScalar invScale = 1.0f / pathData->fScale;
4615bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        dx *= invScale;
4625bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        dy *= invScale;
4635bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        width *= invScale;
4645bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        height *= invScale;
4655bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
46653f26aa045d58feb9f2114f53629024bffe52deajoshualitt        SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
46753f26aa045d58feb9f2114f53629024bffe52deajoshualitt
4685bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // vertex positions
4695bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // TODO make the vertex attributes a struct
4705bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkRect r = SkRect::MakeXYWH(dx, dy, width, height);
4715bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexStride);
4725bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
47353f26aa045d58feb9f2114f53629024bffe52deajoshualitt        // colors
47453f26aa045d58feb9f2114f53629024bffe52deajoshualitt        for (int i = 0; i < kVerticesPerQuad; i++) {
47553f26aa045d58feb9f2114f53629024bffe52deajoshualitt            GrColor* colorPtr = (GrColor*)(offset + sizeof(SkPoint) + i * vertexStride);
47653f26aa045d58feb9f2114f53629024bffe52deajoshualitt            *colorPtr = color;
47753f26aa045d58feb9f2114f53629024bffe52deajoshualitt        }
47853f26aa045d58feb9f2114f53629024bffe52deajoshualitt
47901e583807618038a578a3b07cfad3101d24115c7benjaminwagner        const SkScalar tx = SkIntToScalar(pathData->fAtlasLocation.fX);
48001e583807618038a578a3b07cfad3101d24115c7benjaminwagner        const SkScalar ty = SkIntToScalar(pathData->fAtlasLocation.fY);
48101e583807618038a578a3b07cfad3101d24115c7benjaminwagner
4825bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        // vertex texture coords
48353f26aa045d58feb9f2114f53629024bffe52deajoshualitt        SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(GrColor));
48401e583807618038a578a3b07cfad3101d24115c7benjaminwagner        textureCoords->setRectFan(tx / texture->width(),
48501e583807618038a578a3b07cfad3101d24115c7benjaminwagner                                  ty / texture->height(),
48601e583807618038a578a3b07cfad3101d24115c7benjaminwagner                                  (tx + pathData->fBounds.width()) / texture->width(),
48701e583807618038a578a3b07cfad3101d24115c7benjaminwagner                                  (ty + pathData->fBounds.height())  / texture->height(),
4885bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt                                  vertexStride);
4895bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
490fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
491144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt    void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const {
492cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        GrVertices vertices;
493b5238a7571c243ba4a154a62575570c3078b3741bsalomon        int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads();
494cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon        vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
495b5238a7571c243ba4a154a62575570c3078b3741bsalomon            flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad,
496e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon            kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw);
4977539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon        target->draw(vertices);
498b5238a7571c243ba4a154a62575570c3078b3741bsalomon        flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;
499b5238a7571c243ba4a154a62575570c3078b3741bsalomon        flushInfo->fInstancesToFlush = 0;
5005bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
5015bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
50253f26aa045d58feb9f2114f53629024bffe52deajoshualitt    GrColor color() const { return fGeoData[0].fColor; }
5035bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
5045bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
5055bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
506cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
507abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        AADistanceFieldPathBatch* that = t->cast<AADistanceFieldPathBatch>();
508abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
509abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                                    that->bounds(), caps)) {
5108cab9a7685e872427e6f0388f149575a9b6016eejoshualitt            return false;
5118cab9a7685e872427e6f0388f149575a9b6016eejoshualitt        }
5128cab9a7685e872427e6f0388f149575a9b6016eejoshualitt
51353f26aa045d58feb9f2114f53629024bffe52deajoshualitt        // TODO We can position on the cpu
5145bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
5155bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            return false;
516fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth        }
5175bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
5185bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
51999c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        this->joinBounds(that->bounds());
5205bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        return true;
521fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    }
522fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
5235bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    struct BatchTracker {
5245bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        SkMatrix fViewMatrix;
5255bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        bool fUsesLocalCoords;
5265bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        bool fColorIgnored;
5275bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        bool fCoverageIgnored;
5285bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    };
5295bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
5305bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    BatchTracker fBatch;
5315bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    SkSTArray<1, Geometry, true> fGeoData;
5325bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    GrBatchAtlas* fAtlas;
5335bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    PathCache* fPathCache;
5345bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    PathDataList* fPathList;
5351b55a963a2374a14bb82eb887bb99ee91680f0ebreed
5361b55a963a2374a14bb82eb887bb99ee91680f0ebreed    typedef GrVertexBatch INHERITED;
5375bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt};
5385bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
5390aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) {
540de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt    GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),
541de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt                              "GrAADistanceFieldPathRenderer::onDrawPath");
5425bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    // we've already bailed on inverse filled paths, so this is safe
5430aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    if (args.fPath->isEmpty()) {
5445bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        return true;
5452dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt    }
5462dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt
5475bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    if (!fAtlas) {
548b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt        fAtlas = args.fResourceProvider->createAtlas(kAlpha_8_GrPixelConfig,
549b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
550b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     NUM_PLOTS_X, NUM_PLOTS_Y,
551b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     &GrAADistanceFieldPathRenderer::HandleEviction,
552b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     (void*)this);
55321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        if (!fAtlas) {
5545bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt            return false;
5555bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt        }
5565bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt    }
5575bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
5580aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    AADistanceFieldPathBatch::Geometry geometry(*args.fStroke);
559512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) {
560512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        geometry.fPath = *args.fPath;
561512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    } else {
562512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth        args.fStroke->applyToPath(&geometry.fPath, *args.fPath);
563512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    }
56453f26aa045d58feb9f2114f53629024bffe52deajoshualitt    geometry.fColor = args.fColor;
5650aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    geometry.fAntiAlias = args.fAntiAlias;
566512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // Note: this is the generation ID of the _original_ path. When a new path is
567512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // generated due to stroking it is important that the original path's id is used
568512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    // for caching.
569512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    geometry.fGenID = args.fPath->getGenerationID();
570512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth
57153f26aa045d58feb9f2114f53629024bffe52deajoshualitt    SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry,
572abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                                                                     *args.fViewMatrix, fAtlas,
573abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                                                                     &fPathCache, &fPathList));
5740aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomon    args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
5755bf99f1ca8f30287803b594d06c60a7b6796ad45joshualitt
576fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth    return true;
577fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}
578fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth
57921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt///////////////////////////////////////////////////////////////////////////////////////////////////
58021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
58121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt#ifdef GR_TEST_UTILS
58221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
58321279c7ada1e47e8bfc6375f67768c8eedffb680joshualittstruct PathTestStruct {
58421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    typedef GrAADistanceFieldPathRenderer::PathCache PathCache;
58521279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    typedef GrAADistanceFieldPathRenderer::PathData PathData;
58621279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
58796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    PathTestStruct() : fContextID(SK_InvalidGenID), fAtlas(nullptr) {}
58821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    ~PathTestStruct() { this->reset(); }
58921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
59021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    void reset() {
59121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        PathDataList::Iter iter;
59221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
59321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        PathData* pathData;
59421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        while ((pathData = iter.get())) {
59521279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt            iter.next();
59621279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt            fPathList.remove(pathData);
597385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete pathData;
59821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        }
599385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fAtlas;
6006c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt        fPathCache.reset();
60121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    }
60221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
60321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
60421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        PathTestStruct* dfpr = (PathTestStruct*)pr;
60521279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        // remove any paths that use this plot
60621279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        PathDataList::Iter iter;
60721279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart);
60821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        PathData* pathData;
60921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        while ((pathData = iter.get())) {
61021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt            iter.next();
61121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt            if (id == pathData->fID) {
61221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt                dfpr->fPathCache.remove(pathData->fKey);
61321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt                dfpr->fPathList.remove(pathData);
614385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                delete pathData;
61521279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt            }
61621279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        }
61721279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    }
61821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
61921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    uint32_t fContextID;
62021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    GrBatchAtlas* fAtlas;
62121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    PathCache fPathCache;
62221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    PathDataList fPathList;
62321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt};
62421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
625abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonDRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) {
62621279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    static PathTestStruct gTestStruct;
62721279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
62821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    if (context->uniqueID() != gTestStruct.fContextID) {
62921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        gTestStruct.fContextID = context->uniqueID();
63021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt        gTestStruct.reset();
631b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt        gTestStruct.fAtlas =
632b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                context->resourceProvider()->createAtlas(kAlpha_8_GrPixelConfig,
633b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
634b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     NUM_PLOTS_X, NUM_PLOTS_Y,
635b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     &PathTestStruct::HandleEviction,
636b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt                                                     (void*)&gTestStruct);
63721279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    }
63821279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
63921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    SkMatrix viewMatrix = GrTest::TestMatrix(random);
64021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    GrColor color = GrRandomColor(random);
64121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
64221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random));
64353f26aa045d58feb9f2114f53629024bffe52deajoshualitt    geometry.fColor = color;
64421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    geometry.fPath = GrTest::TestPath(random);
64521279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt    geometry.fAntiAlias = random->nextBool();
646512e437e1e07159a258dd3c5b907576bd1aefc1ejvanverth    geometry.fGenID = random->nextU();
64721279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
64853f26aa045d58feb9f2114f53629024bffe52deajoshualitt    return AADistanceFieldPathBatch::Create(geometry, viewMatrix,
64921279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt                                            gTestStruct.fAtlas,
65021279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt                                            &gTestStruct.fPathCache,
65121279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt                                            &gTestStruct.fPathList);
65221279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt}
65321279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt
65421279c7ada1e47e8bfc6375f67768c8eedffb680joshualitt#endif
655