diff options
author | bsalomon <bsalomon@google.com> | 2016-07-06 11:54:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-07-06 11:54:59 -0700 |
commit | a7d85ba138ee09739defbd277b04c479fdef82a6 (patch) | |
tree | ae5af2c5d489a22c9bb4331238cdd9fa6164ccd0 /src/gpu | |
parent | 52fa668dc589501f5e48a7c5b1958882b86ff496 (diff) |
Add gm that tests shaded stroked rectangles.
Fix GPU handling of previously untested cases.
Move rect->path fallback from SkGpuDevice to GrDrawContext.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2125663003
Review-Url: https://codereview.chromium.org/2125663003
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 65 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 19 | ||||
-rw-r--r-- | src/gpu/batches/GrAAStrokeRectBatch.cpp | 50 | ||||
-rw-r--r-- | src/gpu/batches/GrAAStrokeRectBatch.h | 8 | ||||
-rw-r--r-- | src/gpu/batches/GrNonAAStrokeRectBatch.cpp | 35 | ||||
-rw-r--r-- | src/gpu/batches/GrNonAAStrokeRectBatch.h | 11 | ||||
-rw-r--r-- | src/gpu/batches/GrRectBatchFactory.h | 4 | ||||
-rw-r--r-- | src/gpu/effects/GrDashingEffect.cpp | 2 |
8 files changed, 94 insertions, 100 deletions
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index d057984f9c..5474707191 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -311,11 +311,12 @@ void GrDrawContext::drawRect(const GrClip& clip, AutoCheckFlush acf(fDrawingManager); const SkStrokeRec& stroke = style->strokeRec(); - SkScalar width = stroke.getWidth(); - - // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking - // cases where the RT is fully inside a stroke. - if (width < 0) { + bool useHWAA; + bool snapToPixelCenters = false; + SkAutoTUnref<GrDrawBatch> batch; + if (stroke.getStyle() == SkStrokeRec::kFill_Style) { + // Check if this is a full RT draw and can be replaced with a clear. We don't bother + // checking cases where the RT is fully inside a stroke. SkRect rtRect; fRenderTarget->getBoundsRect(&rtRect); // Does the clip contain the entire RT? @@ -339,32 +340,54 @@ void GrDrawContext::drawRect(const GrClip& clip, } } } - } - - bool useHWAA; - bool snapToPixelCenters = false; - SkAutoTUnref<GrDrawBatch> batch; - if (width < 0) { batch.reset(this->getFillRectBatch(paint, viewMatrix, rect, &useHWAA)); - } else { + } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style || + stroke.getStyle() == SkStrokeRec::kHairline_Style) { + if ((!rect.width() || !rect.height()) && + SkStrokeRec::kHairline_Style != stroke.getStyle()) { + SkScalar r = stroke.getWidth() / 2; + // TODO: Move these stroke->fill fallbacks to GrShape? + switch (stroke.getJoin()) { + case SkPaint::kMiter_Join: + this->drawRect(clip, paint, viewMatrix, + {rect.fLeft - r, rect.fTop - r, + rect.fRight + r, rect.fBottom + r}, + &GrStyle::SimpleFill()); + return; + case SkPaint::kRound_Join: + // Raster draws nothing when both dimensions are empty. + if (rect.width() || rect.height()){ + SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r); + this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill()); + return; + } + case SkPaint::kBevel_Join: + if (!rect.width()) { + this->drawRect(clip, paint, viewMatrix, + {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom}, + &GrStyle::SimpleFill()); + } else { + this->drawRect(clip, paint, viewMatrix, + {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r}, + &GrStyle::SimpleFill()); + } + return; + } + } GrColor color = paint.getColor(); - if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) { // The stroke path needs the rect to remain axis aligned (no rotation or skew). if (viewMatrix.rectStaysRect()) { - batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, - stroke)); + batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke)); } } else { - // Non-AA hairlines are snapped to pixel centers to make which pixels are hit - // deterministic - snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled()); - batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, - width, 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. + snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style && + !fRenderTarget->isUnifiedMultisampled(); + batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, + stroke, snapToPixelCenters)); } } diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 2759a3e185..f6851f1812 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -516,24 +516,9 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRect", fContext); CHECK_SHOULD_DRAW(draw); - bool doStroke = paint.getStyle() != SkPaint::kFill_Style; - SkScalar width = paint.getStrokeWidth(); - - /* - We have special code for hairline strokes, miter-strokes, bevel-stroke - and fills. Anything else we just call our path code. - */ - bool usePath = doStroke && width > 0 && - (paint.getStrokeJoin() == SkPaint::kRound_Join || - (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmpty())); - - // a few other reasons we might need to call drawPath... - if (paint.getMaskFilter() || paint.getPathEffect() || - paint.getStyle() == SkPaint::kStrokeAndFill_Style) { // we can't both stroke and fill rects - usePath = true; - } - if (usePath) { + // A couple reasons we might need to call drawPath. + if (paint.getMaskFilter() || paint.getPathEffect()) { SkPath path; path.setIsVolatile(true); path.addRect(rect); diff --git a/src/gpu/batches/GrAAStrokeRectBatch.cpp b/src/gpu/batches/GrAAStrokeRectBatch.cpp index 98b764aa5b..3e0893236f 100644 --- a/src/gpu/batches/GrAAStrokeRectBatch.cpp +++ b/src/gpu/batches/GrAAStrokeRectBatch.cpp @@ -516,14 +516,25 @@ void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices, } } -inline static bool is_miter(const SkStrokeRec& stroke) { +// We support all hairlines, bevels, and miters, but not round joins. Also, check whether the miter +// limit makes a miter join effectively beveled. +inline static bool allowed_stroke(const SkStrokeRec& stroke, bool* isMiter) { + SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style || + stroke.getStyle() == SkStrokeRec::kHairline_Style); // For hairlines, make bevel and round joins appear the same as mitered ones. - // small miter limit means right angles show bevel... - if ((stroke.getWidth() > 0) && (stroke.getJoin() != SkPaint::kMiter_Join || - stroke.getMiter() < SK_ScalarSqrt2)) { - return false; + if (!stroke.getWidth()) { + *isMiter = true; + return true; } - return true; + if (stroke.getJoin() == SkPaint::kBevel_Join) { + *isMiter = false; + return true; + } + if (stroke.getJoin() == SkPaint::kMiter_Join) { + *isMiter = stroke.getMiter() >= SK_ScalarSqrt2; + return true; + } + return false; } static void compute_rects(SkRect* devOutside, SkRect* devOutsideAssist, SkRect* devInside, @@ -596,7 +607,10 @@ GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, const SkStrokeRec& stroke) { - bool isMiterStroke = is_miter(stroke); + bool isMiterStroke; + if (!allowed_stroke(stroke, &isMiterStroke)) { + return nullptr; + } AAStrokeRectBatch* batch = AAStrokeRectBatch::Create(viewMatrix, isMiterStroke); SkRect devOutside, devOutsideAssist, devInside; @@ -609,28 +623,6 @@ GrDrawBatch* Create(GrColor color, return batch; } -bool Append(GrBatch* origBatch, - GrColor color, - const SkMatrix& viewMatrix, - const SkRect& rect, - const SkStrokeRec& stroke) { - AAStrokeRectBatch* batch = origBatch->cast<AAStrokeRectBatch>(); - - // we can't batch across vm changes - bool isMiterStroke = is_miter(stroke); - if (!batch->canAppend(viewMatrix, isMiterStroke)) { - return false; - } - - SkRect devOutside, devOutsideAssist, devInside; - bool isDegenerate; - compute_rects(&devOutside, &devOutsideAssist, &devInside, &isDegenerate, viewMatrix, - rect, stroke.getWidth(), isMiterStroke); - - batch->appendAndUpdateBounds(color, devOutside, devOutsideAssist, devInside, isDegenerate); - return true; -} - }; /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/batches/GrAAStrokeRectBatch.h b/src/gpu/batches/GrAAStrokeRectBatch.h index e0069a1feb..964cc5b4b9 100644 --- a/src/gpu/batches/GrAAStrokeRectBatch.h +++ b/src/gpu/batches/GrAAStrokeRectBatch.h @@ -29,12 +29,6 @@ GrDrawBatch* Create(GrColor color, const SkRect& rect, const SkStrokeRec& stroke); -bool Append(GrBatch*, - GrColor color, - const SkMatrix& viewMatrix, - const SkRect& rect, - const SkStrokeRec& stroke); - -}; +} #endif diff --git a/src/gpu/batches/GrNonAAStrokeRectBatch.cpp b/src/gpu/batches/GrNonAAStrokeRectBatch.cpp index a38760c362..fb906081d4 100644 --- a/src/gpu/batches/GrNonAAStrokeRectBatch.cpp +++ b/src/gpu/batches/GrNonAAStrokeRectBatch.cpp @@ -211,29 +211,30 @@ private: typedef GrVertexBatch INHERITED; }; +// Allow all hairlines and all miters, so long as the miter limit doesn't produce beveled corners. +inline static bool allowed_stroke(const SkStrokeRec& stroke) { + SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style || + stroke.getStyle() == SkStrokeRec::kHairline_Style); + return !stroke.getWidth() || + (stroke.getJoin() == SkPaint::kMiter_Join && stroke.getMiter() > SK_ScalarSqrt2); +} + namespace GrNonAAStrokeRectBatch { GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, - SkScalar strokeWidth, + const SkStrokeRec& stroke, bool snapToPixelCenters) { + if (!allowed_stroke(stroke)) { + return nullptr; + } NonAAStrokeRectBatch* batch = NonAAStrokeRectBatch::Create(); - batch->append(color, viewMatrix, rect, strokeWidth); + batch->append(color, viewMatrix, rect, stroke.getWidth()); batch->init(snapToPixelCenters); return batch; } -void Append(GrBatch* origBatch, - GrColor color, - const SkMatrix& viewMatrix, - const SkRect& rect, - SkScalar strokeWidth, - bool snapToPixelCenters) { - NonAAStrokeRectBatch* batch = origBatch->cast<NonAAStrokeRectBatch>(); - batch->appendAndUpdateBounds(color, viewMatrix, rect, strokeWidth, snapToPixelCenters); -} - }; #ifdef GR_TEST_UTILS @@ -242,9 +243,13 @@ DRAW_BATCH_TEST_DEFINE(NonAAStrokeRectBatch) { SkMatrix viewMatrix = GrTest::TestMatrix(random); GrColor color = GrRandomColor(random); SkRect rect = GrTest::TestRect(random); - SkScalar strokeWidth = random->nextBool() ? 0.0f : 1.0f; - - return GrNonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeWidth, random->nextBool()); + SkScalar strokeWidth = random->nextBool() ? 0.0f : 2.0f; + SkPaint paint; + paint.setStrokeWidth(strokeWidth); + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeJoin(SkPaint::kMiter_Join); + SkStrokeRec strokeRec(paint); + return GrNonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeRec, random->nextBool()); } #endif diff --git a/src/gpu/batches/GrNonAAStrokeRectBatch.h b/src/gpu/batches/GrNonAAStrokeRectBatch.h index 3cee47dedd..4d94337cc0 100644 --- a/src/gpu/batches/GrNonAAStrokeRectBatch.h +++ b/src/gpu/batches/GrNonAAStrokeRectBatch.h @@ -14,6 +14,7 @@ class GrDrawBatch; struct SkRect; +class SkStrokeRec; class SkMatrix; namespace GrNonAAStrokeRectBatch { @@ -21,15 +22,9 @@ namespace GrNonAAStrokeRectBatch { GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, - SkScalar strokeWidth, + const SkStrokeRec&, bool snapToPixelCenters); -void Append(GrColor color, - const SkMatrix& viewMatrix, - const SkRect& rect, - SkScalar strokeWidth, - bool snapToPixelCenters); - -}; +} #endif diff --git a/src/gpu/batches/GrRectBatchFactory.h b/src/gpu/batches/GrRectBatchFactory.h index 16eeaee02c..4512f6a1f9 100644 --- a/src/gpu/batches/GrRectBatchFactory.h +++ b/src/gpu/batches/GrRectBatchFactory.h @@ -55,9 +55,9 @@ inline GrDrawBatch* CreateAAFill(GrColor color, inline GrDrawBatch* CreateNonAAStroke(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect, - SkScalar strokeWidth, + const SkStrokeRec& strokeRec, bool snapToPixelCenters) { - return GrNonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeWidth, snapToPixelCenters); + return GrNonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeRec, snapToPixelCenters); } inline GrDrawBatch* CreateAAStroke(GrColor color, diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp index ae375409cb..4e82a62195 100644 --- a/src/gpu/effects/GrDashingEffect.cpp +++ b/src/gpu/effects/GrDashingEffect.cpp @@ -1240,7 +1240,7 @@ DRAW_BATCH_TEST_DEFINE(DashBatch) { } // pick random cap - SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::Cap::kCapCount)); + SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount)); SkScalar intervals[2]; |