From ad06544cc6ac4b403a24adda4ee36b9f35b3071f Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Thu, 8 Mar 2018 22:41:33 -0700 Subject: 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 Commit-Queue: Chris Dalton --- src/gpu/ccpr/GrCCPathParser.cpp | 15 +++++++-------- src/gpu/ccpr/GrCCPathParser.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/ccpr/GrCCPathParser.cpp b/src/gpu/ccpr/GrCCPathParser.cpp index 43f5e6be6a..fd0b71da29 100644 --- a/src/gpu/ccpr/GrCCPathParser.cpp +++ b/src/gpu/ccpr/GrCCPathParser.cpp @@ -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(nextPathInfo->fAtlasOffsetX); - atlasOffsetY = static_cast(nextPathInfo->fAtlasOffsetY); + currIndices = &instanceIndices[(int)nextPathInfo->scissorMode()]; + atlasOffsetX = static_cast(nextPathInfo->atlasOffsetX()); + atlasOffsetY = static_cast(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 d8d897f6d5..b1a1ee5906 100644 --- a/src/gpu/ccpr/GrCCPathParser.h +++ b/src/gpu/ccpr/GrCCPathParser.h @@ -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 fFanTessellation; - int fFanTessellationCount = 0; + int fFanTessellationCount = -1; + std::unique_ptr fFanTessellation; }; // Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous -- cgit v1.2.3