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>
This commit is contained in:
Chris Dalton 2018-03-08 22:41:33 -07:00 committed by Skia Commit-Bot
parent c2ef4ab423
commit ad06544cc6
2 changed files with 33 additions and 11 deletions

View File

@ -240,8 +240,7 @@ void GrCCPathParser::saveParsedPath(ScissorMode scissorMode, const SkIRect& clip
}
}
fPathsInfo.back().fFanTessellation.reset(vertices);
fPathsInfo.back().fFanTessellationCount = count;
fPathsInfo.back().adoptFanTessellation(vertices, count);
}
fTotalPrimitiveCounts[(int)scissorMode] += fCurrPathPrimitiveCounts;
@ -408,14 +407,14 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) {
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;

View File

@ -76,14 +76,37 @@ private:
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