ccpr: Fix crash on zero-length fan tessellations
Hardens the path parser to handle zero-length fan tessellations. In this
case the vertex pointer returned by the tessellator will be null, so we
need to indicate whether a tessellation exists in a different way.
Bug: skia:7642
Change-Id: If29df9d08565ff613059f2d3b49ab4eb79908495
Reviewed-on: https://skia-review.googlesource.com/113362
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCPathParser.cpp b/src/gpu/ccpr/GrCCPathParser.cpp
index 43f5e6b..fd0b71d 100644
--- a/src/gpu/ccpr/GrCCPathParser.cpp
+++ b/src/gpu/ccpr/GrCCPathParser.cpp
@@ -240,8 +240,7 @@
}
}
- fPathsInfo.back().fFanTessellation.reset(vertices);
- fPathsInfo.back().fFanTessellationCount = count;
+ fPathsInfo.back().adoptFanTessellation(vertices, count);
}
fTotalPrimitiveCounts[(int)scissorMode] += fCurrPathPrimitiveCounts;
@@ -408,14 +407,14 @@
switch (verb) {
case GrCCGeometry::Verb::kBeginPath:
SkASSERT(currFan.empty());
- currIndices = &instanceIndices[(int)nextPathInfo->fScissorMode];
- atlasOffsetX = static_cast<float>(nextPathInfo->fAtlasOffsetX);
- atlasOffsetY = static_cast<float>(nextPathInfo->fAtlasOffsetY);
+ currIndices = &instanceIndices[(int)nextPathInfo->scissorMode()];
+ atlasOffsetX = static_cast<float>(nextPathInfo->atlasOffsetX());
+ atlasOffsetY = static_cast<float>(nextPathInfo->atlasOffsetY());
atlasOffset = {atlasOffsetX, atlasOffsetY};
- currFanIsTessellated = nextPathInfo->fFanTessellation.get();
+ currFanIsTessellated = nextPathInfo->hasFanTessellation();
if (currFanIsTessellated) {
- emit_tessellated_fan(nextPathInfo->fFanTessellation.get(),
- nextPathInfo->fFanTessellationCount, atlasOffset,
+ emit_tessellated_fan(nextPathInfo->fanTessellation(),
+ nextPathInfo->fanTessellationCount(), atlasOffset,
triPointInstanceData, quadPointInstanceData, currIndices);
}
++nextPathInfo;
diff --git a/src/gpu/ccpr/GrCCPathParser.h b/src/gpu/ccpr/GrCCPathParser.h
index d8d897f..b1a1ee5 100644
--- a/src/gpu/ccpr/GrCCPathParser.h
+++ b/src/gpu/ccpr/GrCCPathParser.h
@@ -76,14 +76,37 @@
using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
// Every kBeginPath verb has a corresponding PathInfo entry.
- struct PathInfo {
+ class PathInfo {
+ public:
PathInfo(ScissorMode scissorMode, int16_t offsetX, int16_t offsetY)
: fScissorMode(scissorMode), fAtlasOffsetX(offsetX), fAtlasOffsetY(offsetY) {}
+ ScissorMode scissorMode() const { return fScissorMode; }
+ int16_t atlasOffsetX() const { return fAtlasOffsetX; }
+ int16_t atlasOffsetY() const { return fAtlasOffsetY; }
+
+ // An empty tessellation fan is also valid; we use negative count to denote not tessellated.
+ bool hasFanTessellation() const { return fFanTessellationCount >= 0; }
+ int fanTessellationCount() const {
+ SkASSERT(this->hasFanTessellation());
+ return fFanTessellationCount;
+ }
+ const GrTessellator::WindingVertex* fanTessellation() const {
+ SkASSERT(this->hasFanTessellation());
+ return fFanTessellation.get();
+ }
+
+ void adoptFanTessellation(const GrTessellator::WindingVertex* vertices, int count) {
+ SkASSERT(count >= 0);
+ fFanTessellation.reset(vertices);
+ fFanTessellationCount = count;
+ }
+
+ private:
ScissorMode fScissorMode;
int16_t fAtlasOffsetX, fAtlasOffsetY;
- std::unique_ptr<GrTessellator::WindingVertex[]> fFanTessellation;
- int fFanTessellationCount = 0;
+ int fFanTessellationCount = -1;
+ std::unique_ptr<const GrTessellator::WindingVertex[]> fFanTessellation;
};
// Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous