GrTessellator: fix event creation for dead boundary edges.

In some cases, an overlap boundary edge can be nulled out by the creation
of a skeleton edge. In that case, we should avoid trying to create
parallel edge events from that dead edge.

This required making the tessellator verb maximum verb count modifiable
at runtime for testing, since the test case has more than 10 vertices.

Also added more logging.

BUG: 966696
Change-Id: I429735999f6297655311485bc68d732b1c48bfce
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/216284
Commit-Queue: Stephen White <senorblanco@chromium.org>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Stephen White 2019-05-29 11:26:16 -04:00 committed by Skia Commit-Bot
parent d0d66fb8be
commit 8a3c059796
4 changed files with 46 additions and 11 deletions

View File

@ -538,16 +538,20 @@ void create_event(SSEdge* edge, Vertex* v, SSEdge* other, Vertex* dest, EventLis
if (!v->fPartner) {
return;
}
Vertex* top = edge->fEdge->fTop;
Vertex* bottom = edge->fEdge->fBottom;
if (!top || !bottom ) {
return;
}
Line line = edge->fEdge->fLine;
line.fC = -(dest->fPoint.fX * line.fA + dest->fPoint.fY * line.fB);
Edge bisector(v, v->fPartner, 1, Edge::Type::kConnector);
SkPoint p;
uint8_t alpha = dest->fAlpha;
if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, edge->fEdge->fTop->fPoint) &&
c.sweep_lt(p, edge->fEdge->fBottom->fPoint)) {
if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, top->fPoint) &&
c.sweep_lt(p, bottom->fPoint)) {
LOG("found p edge event for %g, %g (original %g -> %g), will collapse to %g,%g alpha %d\n",
dest->fID, v->fID, edge->fEdge->fTop->fID, edge->fEdge->fBottom->fID, p.fX, p.fY,
alpha);
dest->fID, v->fID, top->fID, bottom->fID, p.fX, p.fY, alpha);
edge->fEvent = alloc.make<Event>(edge, p, alpha);
events->push(edge->fEvent);
}
@ -1501,14 +1505,18 @@ void dump_mesh(const VertexList& mesh) {
void dump_skel(const SSEdgeList& ssEdges) {
#if LOGGING_ENABLED
LOG("skeleton:\n");
for (SSEdge* edge : ssEdges) {
if (edge->fEdge) {
LOG("skel edge %g -> %g (original %g -> %g)\n",
LOG("skel edge %g -> %g",
edge->fPrev->fVertex->fID,
edge->fNext->fVertex->fID,
edge->fEdge->fTop->fID,
edge->fEdge->fBottom->fID);
edge->fNext->fVertex->fID);
if (edge->fEdge->fTop && edge->fEdge->fBottom) {
LOG(" (original %g -> %g)\n",
edge->fEdge->fTop->fID,
edge->fEdge->fBottom->fID);
} else {
LOG("\n");
}
}
}
#endif
@ -1950,11 +1958,14 @@ bool collapse_overlap_regions(VertexList* mesh, Comparator& c, SkArenaAlloc& all
bool complex = events.size() > 0;
LOG("\ncollapsing overlap regions\n");
LOG("skeleton before:\n");
dump_skel(ssEdges);
while (events.size() > 0) {
Event* event = events.top();
events.pop();
event->apply(mesh, c, &events, alloc);
}
LOG("skeleton after:\n");
dump_skel(ssEdges);
for (SSEdge* edge : ssEdges) {
if (Edge* e = edge->fEdge) {

View File

@ -137,7 +137,8 @@ private:
} // namespace
GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
GrTessellatingPathRenderer::GrTessellatingPathRenderer()
: fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
}
GrPathRenderer::CanDrawPath
@ -161,7 +162,7 @@ GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
// without keys.
SkPath path;
args.fShape->asPath(&path);
if (path.countVerbs() > GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
if (path.countVerbs() > fMaxVerbCount) {
return CanDrawPath::kNo;
}
}

View File

@ -17,6 +17,9 @@
class SK_API GrTessellatingPathRenderer : public GrPathRenderer {
public:
GrTessellatingPathRenderer();
#if GR_TEST_UTILS
void setMaxVerbCount(int maxVerbCount) { fMaxVerbCount = maxVerbCount; }
#endif
private:
CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
@ -26,6 +29,7 @@ private:
}
bool onDrawPath(const DrawPathArgs&) override;
int fMaxVerbCount;
typedef GrPathRenderer INHERITED;
};

View File

@ -622,6 +622,23 @@ static SkPath create_path_43() {
return path;
}
// Reduction from crbug.com/966696
static SkPath create_path_44() {
SkPath path;
path.moveTo(114.4606170654296875, 186.443878173828125);
path.lineTo( 91.5394744873046875, 185.4189453125);
path.lineTo(306.45538330078125, 3203.986083984375);
path.moveTo(16276206965409972224.0, 815.59393310546875);
path.lineTo(-3.541605062372533207e+20, 487.7236328125);
path.lineTo(-3.541605062372533207e+20, 168.204071044921875);
path.lineTo(16276206965409972224.0, 496.07427978515625);
path.moveTo(-3.541605062372533207e+20, 167.00958251953125);
path.lineTo(-3.541605062372533207e+20, 488.32086181640625);
path.lineTo(16276206965409972224.0, 816.78839111328125);
path.lineTo(16276206965409972224.0, 495.47705078125);
return path;
}
static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
SkPoint pts[2] = { {0, 0}, {1, 1} };
@ -642,6 +659,7 @@ static void test_path(GrContext* ctx,
AATypeFlags aaTypeFlags = AATypeFlags::kNone,
std::unique_ptr<GrFragmentProcessor> fp = nullptr) {
GrTessellatingPathRenderer tess;
tess.setMaxVerbCount(100);
GrPaint paint;
paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
@ -728,4 +746,5 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) {
test_path(ctx, rtc.get(), create_path_41(), SkMatrix(), AATypeFlags::kCoverage);
test_path(ctx, rtc.get(), create_path_42());
test_path(ctx, rtc.get(), create_path_43(), SkMatrix(), AATypeFlags::kCoverage);
test_path(ctx, rtc.get(), create_path_44(), SkMatrix(), AATypeFlags::kCoverage);
}