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:
parent
c2ef4ab423
commit
ad06544cc6
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user