From 4c977868bbe100d6d95f9e53cf176d611eceb3dc Mon Sep 17 00:00:00 2001 From: joshualitt Date: Wed, 13 May 2015 08:00:56 -0700 Subject: [PATCH] fix bounds for BW lines, AA Hairlines BUG=skia: Review URL: https://codereview.chromium.org/1123253003 --- src/gpu/GrAAHairLinePathRenderer.cpp | 4 ++++ src/gpu/GrContext.cpp | 25 +++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index c5d8ae1126..3508727e77 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -730,6 +730,10 @@ private: // compute bounds fBounds = geometry.fPath.getBounds(); geometry.fViewMatrix.mapRect(&fBounds); + + // This is b.c. hairlines are notionally infinitely thin so without expansion + // two overlapping lines could be reordered even though they hit the same pixels. + fBounds.outset(0.5f, 0.5f); } bool onCombineIfPossible(GrBatch* t) override { diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index e26c57f9f6..bf62538434 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -404,8 +404,8 @@ public: SkScalar fStrokeWidth; }; - static GrBatch* Create(const Geometry& geometry) { - return SkNEW_ARGS(StrokeRectBatch, (geometry)); + static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) { + return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters)); } const char* name() const override { return "StrokeRectBatch"; } @@ -501,7 +501,7 @@ public: SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } private: - StrokeRectBatch(const Geometry& geometry) { + StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) { this->initClassID(); fBatch.fHairline = geometry.fStrokeWidth == 0; @@ -513,6 +513,11 @@ private: SkScalar rad = SkScalarHalf(geometry.fStrokeWidth); fBounds.outset(rad, rad); geometry.fViewMatrix.mapRect(&fBounds); + + // If our caller snaps to pixel centers then we have to round out the bounds + if (snapToPixelCenters) { + fBounds.roundOut(); + } } /* create a triangle strip that strokes the specified rect. There are 8 @@ -661,13 +666,15 @@ void GrContext::drawRect(GrRenderTarget* rt, geometry.fRect = rect; geometry.fStrokeWidth = width; - SkAutoTUnref batch(StrokeRectBatch::Create(geometry)); + // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic + bool snapToPixelCenters = (0 == width && !rt->isMultisampled()); + SkAutoTUnref batch(StrokeRectBatch::Create(geometry, snapToPixelCenters)); // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA // is enabled because it can cause ugly artifacts. pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, - 0 == width && !rt->isMultisampled()); + snapToPixelCenters); target->drawBatch(&pipelineBuilder, batch); } else { // filled BW rect @@ -1008,6 +1015,12 @@ void GrContext::drawVertices(GrRenderTarget* rt, viewMatrix.mapRect(&bounds); + // If we don't have AA then we outset for a half pixel in each direction to account for + // snapping + if (!paint.isAntiAlias()) { + bounds.outset(0.5f, 0.5f); + } + DrawVerticesBatch::Geometry geometry; geometry.fColor = paint.getColor(); SkAutoTUnref batch(DrawVerticesBatch::Create(geometry, primitiveType, viewMatrix, @@ -1879,7 +1892,7 @@ BATCH_TEST_DEFINE(StrokeRect) { geometry.fRect = GrTest::TestRect(random); geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f; - return StrokeRectBatch::Create(geometry); + return StrokeRectBatch::Create(geometry, random->nextBool()); } static uint32_t seed_vertices(GrPrimitiveType type) { -- 2.34.1