aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-05-21 09:10:53 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-21 21:52:54 +0000
commit4bfb50b904e0e92d10145398eb3a6f8dd7868867 (patch)
treed25bb829a4e5787b423df0c5e19721a8ca48f438
parentbc721ba4be626e3ba753f55341a7019d98044102 (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.cpp51
-rw-r--r--src/gpu/ccpr/GrCCDrawPathsOp.h44
-rw-r--r--src/gpu/ccpr/GrCCSTLList.h61
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp7
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.h3
-rw-r--r--tests/GrCCPRTest.cpp7
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));