Delete GrSTArenaList
The intent of this class was to abstract the internal linked list used
by GrStrokeTessellateOp, but it seems to just make things more
complicated. We have a need now to iterate the list with more freedom
than is offered by GrSTArenaList, so it seems best to just use a plain
C-style linked list instead.
Bug: chromium:1172543
Change-Id: Ia76be83c523bd3c285200099a529ccd3818490b6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372656
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/bench/TessellateBench.cpp b/bench/TessellateBench.cpp
index b9d9a9d..14c7dd1 100644
--- a/bench/TessellateBench.cpp
+++ b/bench/TessellateBench.cpp
@@ -227,10 +227,11 @@
SkDebugf("ERROR: could not create mock context.");
return;
}
+ SkMatrix matrix = SkMatrix::Scale(fMatrixScale, fMatrixScale);
+ GrStrokeTessellator::PathStrokeList pathStroke(fPath, fStrokeRec, SK_PMColor4fWHITE);
for (int i = 0; i < loops; ++i) {
- SkMatrix matrix = SkMatrix::Scale(fMatrixScale, fMatrixScale);
- GrStrokeHardwareTessellator tessellator(ShaderFlags::kNone, {fPath, fStrokeRec,
- SK_PMColor4fWHITE}, fPath.countVerbs(),
+ GrStrokeHardwareTessellator tessellator(ShaderFlags::kNone, &pathStroke,
+ fPath.countVerbs(),
*fTarget->caps().shaderCaps());
tessellator.prepare(fTarget.get(), matrix);
}
@@ -270,9 +271,10 @@
}
for (int i = 0; i < loops; ++i) {
for (const SkPath& path : fPaths) {
+ GrStrokeTessellator::PathStrokeList pathStroke(path, fStrokeRec, SK_PMColor4fWHITE);
GrStrokeIndirectTessellator tessellator(ShaderFlags::kNone, SkMatrix::I(),
- {path, fStrokeRec, SK_PMColor4fWHITE},
- path.countVerbs(), fTarget->allocator());
+ &pathStroke, path.countVerbs(),
+ fTarget->allocator());
tessellator.prepare(fTarget.get(), SkMatrix::I());
}
fTarget->resetAllocator();
diff --git a/gn/gpu.gni b/gn/gpu.gni
index ce7c2813..d554c49 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -199,7 +199,6 @@
"$_src/gpu/GrSPIRVUniformHandler.h",
"$_src/gpu/GrSPIRVVaryingHandler.cpp",
"$_src/gpu/GrSPIRVVaryingHandler.h",
- "$_src/gpu/GrSTArenaList.h",
"$_src/gpu/GrSWMaskHelper.cpp",
"$_src/gpu/GrSWMaskHelper.h",
"$_src/gpu/GrSamplePatternDictionary.cpp",
diff --git a/src/gpu/GrSTArenaList.h b/src/gpu/GrSTArenaList.h
deleted file mode 100644
index 5a4c530..0000000
--- a/src/gpu/GrSTArenaList.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2020 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrSTArenaList_DEFINED
-#define GrSTArenaList_DEFINED
-
-#include "src/core/SkArenaAlloc.h"
-
-// A singly-linked list whose head element is a "stack allocated" class member and whose subsequent
-// elements are allocated in an SkArenaAlloc.
-template<typename T> class GrSTArenaList {
-public:
- struct Node {
- template <typename... Args>
- Node(Args&&... elementArgs) : fElement(std::forward<Args>(elementArgs)...) {}
- T fElement;
- Node* fNext = nullptr;
- };
-
- template <typename... Args>
- GrSTArenaList(Args&&... headArgs) : fHead(std::forward<Args>(headArgs)...) {}
-
- const T& head() const { return fHead.fElement; }
- T& head() { return fHead.fElement; }
-
- void concat(GrSTArenaList&& list, SkArenaAlloc* allocator) {
- Node* listHeadCopy = allocator->make<Node>(std::move(list.fHead));
- fTail->fNext = listHeadCopy;
- // If the list's fTail pointed to its locally allocated head element, then point our fTail
- // at the copy we just made in the arena. Otherwise the list's fTail already points at an
- // arena-allocated element, so keep it.
- fTail = (list.fTail == &list.fHead) ? listHeadCopy : list.fTail;
- }
-
- struct Iter {
- bool operator!=(const Iter& it) const { return fCurr != it.fCurr; }
- bool operator==(const Iter& it) const { return fCurr == it.fCurr; }
- void operator++() { fCurr = fCurr->fNext; }
- const T& operator*() { return fCurr->fElement; }
- const Node* fCurr;
- };
-
- Iter begin() const { return Iter{&fHead}; }
- Iter end() const { return Iter{nullptr}; }
-
-private:
- Node fHead;
- Node* fTail = &fHead;
-};
-
-#endif
diff --git a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp
index c6897f7..4b122b3 100644
--- a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp
+++ b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp
@@ -655,8 +655,8 @@
PatchWriter patchWriter(fShaderFlags, target, &fPatchChunks, fTotalCombinedVerbCnt);
const SkStrokeRec* strokeForTolerances = nullptr;
- for (const auto& pathStroke : fPathStrokeList) {
- const SkStrokeRec& stroke = pathStroke.fStroke;
+ for (PathStrokeList* pathStroke = fPathStrokeList; pathStroke; pathStroke = pathStroke->fNext) {
+ const SkStrokeRec& stroke = pathStroke->fStroke;
if (!strokeForTolerances || strokeForTolerances->getWidth() != stroke.getWidth() ||
strokeForTolerances->getCap() != stroke.getCap()) {
auto tolerances = Tolerances::MakePreTransform(matrixScales.data(), stroke.getWidth());
@@ -667,10 +667,10 @@
patchWriter.updateDynamicStroke(stroke);
}
if (fShaderFlags & ShaderFlags::kDynamicColor) {
- patchWriter.updateDynamicColor(pathStroke.fColor);
+ patchWriter.updateDynamicColor(pathStroke->fColor);
}
- const SkPath& path = pathStroke.fPath;
+ const SkPath& path = pathStroke->fPath;
auto strokeJoinType = JoinType(stroke.getJoin());
SkPathVerb previousVerb = SkPathVerb::kClose;
for (auto [verb, p, w] : SkPathPriv::Iterate(path)) {
diff --git a/src/gpu/tessellate/GrStrokeHardwareTessellator.h b/src/gpu/tessellate/GrStrokeHardwareTessellator.h
index 37a4041..63f7fe0 100644
--- a/src/gpu/tessellate/GrStrokeHardwareTessellator.h
+++ b/src/gpu/tessellate/GrStrokeHardwareTessellator.h
@@ -26,8 +26,7 @@
int fBasePatch;
};
- GrStrokeHardwareTessellator(ShaderFlags shaderFlags,
- GrSTArenaList<PathStroke>&& pathStrokeList,
+ GrStrokeHardwareTessellator(ShaderFlags shaderFlags, PathStrokeList* pathStrokeList,
int totalCombinedVerbCnt, const GrShaderCaps& shaderCaps)
: GrStrokeTessellator(shaderFlags, std::move(pathStrokeList))
, fTotalCombinedVerbCnt(totalCombinedVerbCnt) {
diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
index b3ae838..799a65f 100644
--- a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
+++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
@@ -441,7 +441,7 @@
GrStrokeIndirectTessellator::GrStrokeIndirectTessellator(ShaderFlags shaderFlags,
const SkMatrix& viewMatrix,
- GrSTArenaList<PathStroke>&& pathStrokeList,
+ PathStrokeList* pathStrokeList,
int totalCombinedVerbCnt,
SkArenaAlloc* alloc)
: GrStrokeTessellator(shaderFlags, std::move(pathStrokeList)) {
@@ -464,8 +464,8 @@
float lastStrokeWidth = -1;
SkPoint lastControlPoint = {0,0};
- for (const auto& pathStroke : fPathStrokeList) {
- const SkStrokeRec& stroke = pathStroke.fStroke;
+ for (PathStrokeList* pathStroke = fPathStrokeList; pathStroke; pathStroke = pathStroke->fNext) {
+ const SkStrokeRec& stroke = pathStroke->fStroke;
SkASSERT(stroke.getWidth() >= 0); // Otherwise we can't initialize lastStrokeWidth=-1.
if (stroke.getWidth() != lastStrokeWidth ||
(stroke.getJoin() == SkPaint::kRound_Join) != counter.isRoundJoin()) {
@@ -475,7 +475,7 @@
fMaxNumExtraEdgesInJoin = std::max(fMaxNumExtraEdgesInJoin,
GrStrokeTessellateShader::NumExtraEdgesInIndirectJoin(stroke.getJoin()));
// Iterate through each verb in the stroke, counting its resolveLevel(s).
- GrStrokeIterator iter(pathStroke.fPath, &stroke, &viewMatrix);
+ GrStrokeIterator iter(pathStroke->fPath, &stroke, &viewMatrix);
while (iter.next()) {
using Verb = GrStrokeIterator::Verb;
Verb verb = iter.verb();
@@ -816,17 +816,17 @@
int8_t resolveLevel;
// Now write out each instance to its resolveLevel's designated location in the instance buffer.
- for (const auto& pathStroke : fPathStrokeList) {
- const SkStrokeRec& stroke = pathStroke.fStroke;
+ for (PathStrokeList* pathStroke = fPathStrokeList; pathStroke; pathStroke = pathStroke->fNext) {
+ const SkStrokeRec& stroke = pathStroke->fStroke;
SkASSERT(stroke.getJoin() != SkPaint::kMiter_Join || numExtraEdgesInJoin == 4);
bool isRoundJoin = (stroke.getJoin() == SkPaint::kRound_Join);
if (fShaderFlags & ShaderFlags::kDynamicStroke) {
binningWriter.updateDynamicStroke(stroke);
}
if (fShaderFlags & ShaderFlags::kDynamicColor) {
- binningWriter.updateDynamicColor(pathStroke.fColor);
+ binningWriter.updateDynamicColor(pathStroke->fColor);
}
- GrStrokeIterator iter(pathStroke.fPath, &stroke, &viewMatrix);
+ GrStrokeIterator iter(pathStroke->fPath, &stroke, &viewMatrix);
bool hasLastControlPoint = false;
while (iter.next()) {
using Verb = GrStrokeIterator::Verb;
diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.h b/src/gpu/tessellate/GrStrokeIndirectTessellator.h
index 9552ff3..8af6d6c 100644
--- a/src/gpu/tessellate/GrStrokeIndirectTessellator.h
+++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.h
@@ -22,7 +22,7 @@
// become an issue if we try to draw a stroke with an astronomically wide width.
constexpr static int8_t kMaxResolveLevel = 15;
- GrStrokeIndirectTessellator(ShaderFlags, const SkMatrix&, GrSTArenaList<PathStroke>&&,
+ GrStrokeIndirectTessellator(ShaderFlags, const SkMatrix&, PathStrokeList*,
int totalCombinedVerbCnt, SkArenaAlloc*);
// Adds the given tessellator to our chain. The chained tessellators all append to a shared
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.cpp b/src/gpu/tessellate/GrStrokeTessellateOp.cpp
index f8fbfea..a278b0b 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.cpp
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.cpp
@@ -63,7 +63,7 @@
bool hasMixedSampledCoverage,
GrClampType clampType) {
// Make sure the finalize happens before combining. We might change fNeedsStencil here.
- SkASSERT(fPathStrokeList.begin().fCurr->fNext == nullptr);
+ SkASSERT(fPathStrokeList.fNext == nullptr);
SkASSERT(fAAType != GrAAType::kCoverage || hasMixedSampledCoverage);
const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
this->headColor(), GrProcessorAnalysisCoverage::kNone, clip,
@@ -120,9 +120,16 @@
return CombineResult::kMayChain;
}
- fPathStrokeList.concat(std::move(op->fPathStrokeList), alloc);
- fTotalCombinedVerbCnt += op->fTotalCombinedVerbCnt;
fShaderFlags = combinedFlags;
+
+ // Concat the op's PathStrokeList. Since the head element is allocated inside the op, we need to
+ // copy it.
+ auto* headCopy = alloc->make<PathStrokeList>(std::move(op->fPathStrokeList));
+ *fPathStrokeTail = headCopy;
+ fPathStrokeTail = (op->fPathStrokeTail == &op->fPathStrokeList.fNext) ? &headCopy->fNext
+ : op->fPathStrokeTail;
+
+ fTotalCombinedVerbCnt += op->fTotalCombinedVerbCnt;
return CombineResult::kMerged;
}
@@ -163,8 +170,7 @@
if (this->canUseHardwareTessellation(caps) &&
((fShaderFlags & ShaderFlags::kDynamicColor) || fTotalCombinedVerbCnt > 50)) {
SkASSERT(!this->nextInChain()); // We never chain when hw tessellation is an option.
- fTessellator = arena->make<GrStrokeHardwareTessellator>(fShaderFlags,
- std::move(fPathStrokeList),
+ fTessellator = arena->make<GrStrokeHardwareTessellator>(fShaderFlags, &fPathStrokeList,
fTotalCombinedVerbCnt,
*caps.shaderCaps());
shaderMode = GrStrokeTessellateShader::Mode::kTessellation;
@@ -184,15 +190,14 @@
}
}
auto* headTessellator = arena->make<GrStrokeIndirectTessellator>(
- fShaderFlags, fViewMatrix, std::move(fPathStrokeList), fTotalCombinedVerbCnt,
- arena);
+ fShaderFlags, fViewMatrix, &fPathStrokeList, fTotalCombinedVerbCnt, arena);
// Make a tessellator for every chained op after us. These will all append to the head
// tessellator's shared indirect-draw list during prepare().
for (GrStrokeTessellateOp* op = this->nextInChain(); op; op = op->nextInChain()) {
SkASSERT(fViewMatrix == op->fViewMatrix);
auto* chainedTessellator = arena->make<GrStrokeIndirectTessellator>(
- fShaderFlags, fViewMatrix, std::move(op->fPathStrokeList),
- op->fTotalCombinedVerbCnt, arena);
+ fShaderFlags, fViewMatrix, &op->fPathStrokeList, op->fTotalCombinedVerbCnt,
+ arena);
headTessellator->addToChain(chainedTessellator);
}
fTessellator = headTessellator;
diff --git a/src/gpu/tessellate/GrStrokeTessellateOp.h b/src/gpu/tessellate/GrStrokeTessellateOp.h
index 819d69e..feb2f78 100644
--- a/src/gpu/tessellate/GrStrokeTessellateOp.h
+++ b/src/gpu/tessellate/GrStrokeTessellateOp.h
@@ -9,7 +9,6 @@
#define GrStrokeTessellateOp_DEFINED
#include "include/core/SkStrokeRec.h"
-#include "src/gpu/GrSTArenaList.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
#include "src/gpu/tessellate/GrPathShader.h"
#include "src/gpu/tessellate/GrStrokeTessellateShader.h"
@@ -21,16 +20,17 @@
public:
using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
- struct PathStroke {
- PathStroke(const SkPath& path, const SkStrokeRec& stroke, const SkPMColor4f& color)
+ struct PathStrokeList {
+ PathStrokeList(const SkPath& path, const SkStrokeRec& stroke, const SkPMColor4f& color)
: fPath(path), fStroke(stroke), fColor(color) {}
SkPath fPath;
SkStrokeRec fStroke;
SkPMColor4f fColor;
+ PathStrokeList* fNext = nullptr;
};
- GrStrokeTessellator(ShaderFlags shaderFlags, GrSTArenaList<PathStroke>&& pathStrokeList)
- : fShaderFlags(shaderFlags), fPathStrokeList(std::move(pathStrokeList)) {}
+ GrStrokeTessellator(ShaderFlags shaderFlags, PathStrokeList* pathStrokeList)
+ : fShaderFlags(shaderFlags), fPathStrokeList(pathStrokeList) {}
// Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
virtual void prepare(GrMeshDrawOp::Target*, const SkMatrix&) = 0;
@@ -43,7 +43,7 @@
protected:
const ShaderFlags fShaderFlags;
- const GrSTArenaList<PathStroke> fPathStrokeList;
+ PathStrokeList* fPathStrokeList;
};
// Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
@@ -54,11 +54,11 @@
private:
using ShaderFlags = GrStrokeTessellateShader::ShaderFlags;
- using PathStroke = GrStrokeTessellator::PathStroke;
+ using PathStrokeList = GrStrokeTessellator::PathStrokeList;
DEFINE_OP_CLASS_ID
- SkStrokeRec& headStroke() { return fPathStrokeList.head().fStroke; }
- SkPMColor4f& headColor() { return fPathStrokeList.head().fColor; }
+ SkStrokeRec& headStroke() { return fPathStrokeList.fStroke; }
+ SkPMColor4f& headColor() { return fPathStrokeList.fColor; }
GrStrokeTessellateOp* nextInChain() const {
return static_cast<GrStrokeTessellateOp*>(this->GrDrawOp::nextInChain());
}
@@ -103,7 +103,8 @@
const GrAAType fAAType;
const SkMatrix fViewMatrix;
ShaderFlags fShaderFlags = ShaderFlags::kNone;
- GrSTArenaList<PathStroke> fPathStrokeList;
+ PathStrokeList fPathStrokeList;
+ PathStrokeList** fPathStrokeTail = &fPathStrokeList.fNext;
int fTotalCombinedVerbCnt = 0;
GrProcessorSet fProcessors;
bool fNeedsStencil = false;
diff --git a/tests/StrokeIndirectTest.cpp b/tests/StrokeIndirectTest.cpp
index b920b77..9b67b66 100644
--- a/tests/StrokeIndirectTest.cpp
+++ b/tests/StrokeIndirectTest.cpp
@@ -41,9 +41,10 @@
for (int i = 0; i < 16; ++i) {
float scale = ldexpf(rand.nextF() + 1, i);
auto matrix = SkMatrix::Scale(scale, scale);
+ GrStrokeTessellator::PathStrokeList pathStrokeList(path, stroke, SK_PMColor4fWHITE);
GrStrokeIndirectTessellator tessellator(GrStrokeTessellateShader::ShaderFlags::kNone,
- matrix, {path, stroke, SK_PMColor4fWHITE},
- path.countVerbs(), target->allocator());
+ matrix, &pathStrokeList, path.countVerbs(),
+ target->allocator());
tessellator.verifyResolveLevels(r, target, matrix, path, stroke);
tessellator.prepare(target, matrix);
tessellator.verifyBuffers(r, target, matrix, stroke);