diff options
author | Chris Dalton <csmartdalton@google.com> | 2018-05-21 09:10:53 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-21 21:52:54 +0000 |
commit | 4bfb50b904e0e92d10145398eb3a6f8dd7868867 (patch) | |
tree | d25bb829a4e5787b423df0c5e19721a8ca48f438 | |
parent | bc721ba4be626e3ba753f55341a7019d98044102 (diff) |
ccpr: Abstract the draws list in a separate class
Bug: skia:
Change-Id: I583c1bdc470e5830d041955d14b164fc00d5d014
Reviewed-on: https://skia-review.googlesource.com/129227
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r-- | src/gpu/ccpr/GrCCDrawPathsOp.cpp | 51 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCCDrawPathsOp.h | 44 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCCSTLList.h | 61 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp | 7 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCoverageCountingPathRenderer.h | 3 | ||||
-rw-r--r-- | tests/GrCCPRTest.cpp | 7 |
6 files changed, 117 insertions, 56 deletions
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp index 68a3d9c296..d239812241 100644 --- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp +++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp @@ -15,15 +15,13 @@ GrCCDrawPathsOp::GrCCDrawPathsOp(GrCoverageCountingPathRenderer* ccpr, GrPaint&& paint, const SkIRect& clipIBounds, const SkMatrix& viewMatrix, const SkPath& path, const SkRect& devBounds) - : INHERITED(ClassID()) + : GrDrawOp(ClassID()) , fCCPR(ccpr) - , fHeadDraw{clipIBounds, viewMatrix, path, paint.getColor(), nullptr} , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint)) + , fDraws({clipIBounds, viewMatrix, path, paint.getColor(), nullptr}) , fProcessors(std::move(paint)) { SkDEBUGCODE(fCCPR->incrDrawOpCount_debugOnly()); SkDEBUGCODE(fBaseInstance = -1); - SkDEBUGCODE(fInstanceCount = 1); - SkDEBUGCODE(fNumSkippedInstances = 0); // FIXME: intersect with clip bounds to (hopefully) improve batching. // (This is nontrivial due to assumptions in generating the octagon cover geometry.) this->setBounds(devBounds, GrOp::HasAABloat::kYes, GrOp::IsZeroArea::kNo); @@ -42,11 +40,10 @@ GrDrawOp::RequiresDstTexture GrCCDrawPathsOp::finalize(const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped) { SkASSERT(!fCCPR->isFlushing_debugOnly()); // There should only be one single path draw in this Op right now. - SkASSERT(1 == fInstanceCount); - SkASSERT(&fHeadDraw == fTailDraw); + SkASSERT(1 == fNumDraws); GrProcessorSet::Analysis analysis = - fProcessors.finalize(fHeadDraw.fColor, GrProcessorAnalysisCoverage::kSingleChannel, - clip, false, caps, dstIsClamped, &fHeadDraw.fColor); + fProcessors.finalize(fDraws.head().fColor, GrProcessorAnalysisCoverage::kSingleChannel, + clip, false, caps, dstIsClamped, &fDraws.head().fColor); return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo; } @@ -55,22 +52,20 @@ bool GrCCDrawPathsOp::onCombineIfPossible(GrOp* op, const GrCaps& caps) { SkASSERT(fCCPR == that->fCCPR); SkASSERT(!fCCPR->isFlushing_debugOnly()); SkASSERT(fOwningRTPendingPaths); - SkASSERT(fInstanceCount); + SkASSERT(fNumDraws); SkASSERT(!that->fOwningRTPendingPaths || that->fOwningRTPendingPaths == fOwningRTPendingPaths); - SkASSERT(that->fInstanceCount); + SkASSERT(that->fNumDraws); if (this->getFillType() != that->getFillType() || fSRGBFlags != that->fSRGBFlags || fProcessors != that->fProcessors) { return false; } - fTailDraw->fNext = &fOwningRTPendingPaths->fDrawsAllocator.push_back(that->fHeadDraw); - fTailDraw = (that->fTailDraw == &that->fHeadDraw) ? fTailDraw->fNext : that->fTailDraw; - + fDraws.append(std::move(that->fDraws), &fOwningRTPendingPaths->fAllocator); this->joinBounds(*that); - SkDEBUGCODE(fInstanceCount += that->fInstanceCount); - SkDEBUGCODE(that->fInstanceCount = 0); + SkDEBUGCODE(fNumDraws += that->fNumDraws); + SkDEBUGCODE(that->fNumDraws = 0); return true; } @@ -80,21 +75,30 @@ void GrCCDrawPathsOp::wasRecorded(GrRenderTargetOpList* opList) { fOwningRTPendingPaths->fDrawOps.addToTail(this); } +int GrCCDrawPathsOp::countPaths(GrCCPathParser::PathStats* stats) const { + int numPaths = 0; + for (const GrCCDrawPathsOp::SingleDraw& draw : fDraws) { + stats->statPath(draw.fPath); + ++numPaths; + } + return numPaths; +} + void GrCCDrawPathsOp::setupResources(GrCCPerFlushResources* resources, GrOnFlushResourceProvider* onFlushRP) { const GrCCAtlas* currentAtlas = nullptr; - SkASSERT(fInstanceCount > 0); + SkASSERT(fNumDraws > 0); SkASSERT(-1 == fBaseInstance); fBaseInstance = resources->pathInstanceCount(); - for (const SingleDraw* draw = this->head(); draw; draw = draw->fNext) { + for (const SingleDraw& draw : fDraws) { // addPathToAtlas gives us two tight bounding boxes: one in device space, as well as a // second one rotated an additional 45 degrees. The path vertex shader uses these two // bounding boxes to generate an octagon that circumscribes the path. SkRect devBounds, devBounds45; int16_t atlasOffsetX, atlasOffsetY; - GrCCAtlas* atlas = resources->addPathToAtlas(*onFlushRP->caps(), draw->fClipIBounds, - draw->fMatrix, draw->fPath, &devBounds, + GrCCAtlas* atlas = resources->addPathToAtlas(*onFlushRP->caps(), draw.fClipIBounds, + draw.fMatrix, draw.fPath, &devBounds, &devBounds45, &atlasOffsetX, &atlasOffsetY); if (!atlas) { SkDEBUGCODE(++fNumSkippedInstances); @@ -107,18 +111,17 @@ void GrCCDrawPathsOp::setupResources(GrCCPerFlushResources* resources, currentAtlas = atlas; } - const SkMatrix& m = draw->fMatrix; + const SkMatrix& m = draw.fMatrix; resources->appendDrawPathInstance( devBounds, devBounds45, {{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}}, {{m.getTranslateX(), m.getTranslateY()}}, {{atlasOffsetX, atlasOffsetY}}, - draw->fColor); + draw.fColor); } - SkASSERT(resources->pathInstanceCount() == - fBaseInstance + fInstanceCount - fNumSkippedInstances); + SkASSERT(resources->pathInstanceCount() == fBaseInstance + fNumDraws - fNumSkippedInstances); if (currentAtlas) { this->addAtlasBatch(currentAtlas, resources->pathInstanceCount()); } @@ -157,5 +160,5 @@ void GrCCDrawPathsOp::onExecute(GrOpFlushState* flushState) { baseInstance, batch.fEndInstanceIdx, this->bounds()); } - SkASSERT(baseInstance == fBaseInstance + fInstanceCount - fNumSkippedInstances); + SkASSERT(baseInstance == fBaseInstance + fNumDraws - fNumSkippedInstances); } diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h index aad8508fb0..77223171de 100644 --- a/src/gpu/ccpr/GrCCDrawPathsOp.h +++ b/src/gpu/ccpr/GrCCDrawPathsOp.h @@ -9,7 +9,9 @@ #define GrCCDrawPathsOp_DEFINED #include "SkTInternalLList.h" +#include "ccpr/GrCCPathParser.h" #include "ccpr/GrCCPathProcessor.h" +#include "ccpr/GrCCSTLList.h" #include "ops/GrDrawOp.h" class GrCCAtlas; @@ -29,21 +31,6 @@ public: const SkMatrix&, const SkPath&, const SkRect& devBounds); ~GrCCDrawPathsOp() override; - struct SingleDraw { - SkIRect fClipIBounds; - SkMatrix fMatrix; - SkPath fPath; - GrColor fColor; - SingleDraw* fNext; - }; - - const SingleDraw* head() const { - SkASSERT(fInstanceCount >= 1); - return &fHeadDraw; - } - - SkDEBUGCODE(int numSkippedInstances_debugOnly() const { return fNumSkippedInstances; }) - const char* name() const override { return "GrCCDrawOp"; } FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*, @@ -55,14 +42,16 @@ public: } void onPrepare(GrOpFlushState*) override {} + int countPaths(GrCCPathParser::PathStats*) const; void setupResources(GrCCPerFlushResources*, GrOnFlushResourceProvider*); + SkDEBUGCODE(int numSkippedInstances_debugOnly() const { return fNumSkippedInstances; }) void onExecute(GrOpFlushState*) override; private: SkPath::FillType getFillType() const { - SkASSERT(fInstanceCount >= 1); - return fHeadDraw.fPath.getFillType(); + SkASSERT(fNumDraws >= 1); + return fDraws.head().fPath.getFillType(); } struct AtlasBatch { @@ -78,20 +67,25 @@ private: } GrCoverageCountingPathRenderer* const fCCPR; - GrCCRTPendingPaths* fOwningRTPendingPaths = nullptr; + const uint32_t fSRGBFlags; - SingleDraw fHeadDraw; - SingleDraw* fTailDraw = &fHeadDraw; + struct SingleDraw { + SkIRect fClipIBounds; + SkMatrix fMatrix; + SkPath fPath; + GrColor fColor; + SingleDraw* fNext; + }; + + GrCCSTLList<SingleDraw> fDraws; + SkDEBUGCODE(int fNumDraws = 1); - const uint32_t fSRGBFlags; GrProcessorSet fProcessors; + GrCCRTPendingPaths* fOwningRTPendingPaths = nullptr; int fBaseInstance; - SkDEBUGCODE(int fInstanceCount); - SkDEBUGCODE(int fNumSkippedInstances); SkSTArray<1, AtlasBatch, true> fAtlasBatches; - - typedef GrDrawOp INHERITED; + SkDEBUGCODE(int fNumSkippedInstances = 0); }; #endif diff --git a/src/gpu/ccpr/GrCCSTLList.h b/src/gpu/ccpr/GrCCSTLList.h new file mode 100644 index 0000000000..3b478e9842 --- /dev/null +++ b/src/gpu/ccpr/GrCCSTLList.h @@ -0,0 +1,61 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrCCSTLList_DEFINED +#define GrCCSTLList_DEFINED + +#include "SkArenaAlloc.h" + +/** + * A singly-linked list whose head element is a local class member. This is required by + * GrCCDrawPathsOp because the owning opList is unknown at the time of creation, so we can't use its + * associated allocator to create the first element. + */ +template<typename T> class GrCCSTLList { +public: + GrCCSTLList(T&& head) : fHead(std::move(head)) {} + + ~GrCCSTLList() { + T* draw = fHead.fNext; // fHead will be destructed automatically. + while (draw) { + T* next = draw->fNext; + draw->~T(); + draw = next; + } + } + + const T& head() const { return fHead; } + T& head() { return fHead; } + + void append(GrCCSTLList&& right, SkArenaAlloc* alloc) { + T* nextTail = (&right.fHead == right.fTail) ? nullptr : right.fTail; + T* newRightHead = + new (alloc->makeBytesAlignedTo(sizeof(T), alignof(T))) T(std::move(right.fHead)); + + // Finish the move of right.fHead. + right.fHead.fNext = nullptr; + right.fTail = &right.fHead; + + fTail->fNext = newRightHead; + fTail = !nextTail ? newRightHead : nextTail; + } + + struct Iter { + bool operator!=(const Iter& that) { return fCurr != that.fCurr; } + const T& operator*() { return *fCurr; } + void operator++() { fCurr = fCurr->fNext; } + const T* fCurr; + }; + Iter begin() const { return Iter{&fHead}; } + Iter end() const { return Iter{nullptr}; } + +private: + T fHead; + T* fTail = &fHead; +}; + +#endif diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp index 0416f1c1da..35ac86c542 100644 --- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp +++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp @@ -180,12 +180,8 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush const GrCCRTPendingPaths& rtPendingPaths = iter->second; for (const GrCCDrawPathsOp* op : rtPendingPaths.fDrawOps) { - for (const GrCCDrawPathsOp::SingleDraw* draw = op->head(); draw; draw = draw->fNext) { - flushingPathStats.statPath(draw->fPath); - ++numPathDraws; - } + numPathDraws += op->countPaths(&flushingPathStats); } - for (const auto& clipsIter : rtPendingPaths.fClipPaths) { flushingPathStats.statPath(clipsIter.second.deviceSpacePath()); } @@ -213,7 +209,6 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush op->setupResources(resources.get(), onFlushRP); SkDEBUGCODE(numSkippedPaths += op->numSkippedInstances_debugOnly()); } - for (auto& clipsIter : rtPendingPaths->fClipPaths) { clipsIter.second.placePathInAtlas(resources.get(), onFlushRP); } diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h index 2eac93369c..93f767fce2 100644 --- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h +++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h @@ -10,6 +10,7 @@ #include "GrPathRenderer.h" #include "GrRenderTargetOpList.h" +#include "SkArenaAlloc.h" #include "SkTInternalLList.h" #include "ccpr/GrCCClipPath.h" #include "ccpr/GrCCDrawPathsOp.h" @@ -34,7 +35,7 @@ struct GrCCRTPendingPaths { SkTInternalLList<GrCCDrawPathsOp> fDrawOps; std::map<uint32_t, GrCCClipPath> fClipPaths; - GrSTAllocator<256, GrCCDrawPathsOp::SingleDraw> fDrawsAllocator; + SkSTArenaAlloc<10 * 1024> fAllocator{10 * 1024 * 2}; }; /** diff --git a/tests/GrCCPRTest.cpp b/tests/GrCCPRTest.cpp index 6f0d8852d9..8cde797f43 100644 --- a/tests/GrCCPRTest.cpp +++ b/tests/GrCCPRTest.cpp @@ -175,6 +175,13 @@ class GrCCPRTest_cleanup : public CCPRTest { // Ensure paths get unreffed. for (int i = 0; i < 10; ++i) { ccpr.drawPath(fPath); + } + REPORTER_ASSERT(reporter, !SkPathPriv::TestingOnly_unique(fPath)); + ccpr.flush(); + REPORTER_ASSERT(reporter, SkPathPriv::TestingOnly_unique(fPath)); + + // Ensure clip paths get unreffed. + for (int i = 0; i < 10; ++i) { ccpr.clipFullscreenRect(fPath); } REPORTER_ASSERT(reporter, !SkPathPriv::TestingOnly_unique(fPath)); |