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