Chromium Code Reviews| Index: src/gpu/GrContext.cpp |
| diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp |
| index c5353abffd10ff47c7d4e9f26067b8638da7c982..2b4f2315b200de4c07c73efe38bce962b952cf45 100644 |
| --- a/src/gpu/GrContext.cpp |
| +++ b/src/gpu/GrContext.cpp |
| @@ -25,6 +25,7 @@ |
| #include "GrSoftwarePathRenderer.h" |
| #include "GrStencilBuffer.h" |
| #include "GrTextStrike.h" |
| +#include "SkDrawProcs.h" |
| #include "SkRTConf.h" |
| #include "SkRRect.h" |
| #include "SkStrokeRec.h" |
| @@ -1037,7 +1038,7 @@ void GrContext::drawRRect(const GrPaint& paint, |
| if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) { |
| SkPath path; |
| path.addRRect(rect); |
| - this->internalDrawPath(target, useAA, path, stroke); |
| + this->internalDrawPath(target, paint, useAA, path, stroke); |
| } |
| } |
| @@ -1061,7 +1062,7 @@ void GrContext::drawOval(const GrPaint& paint, |
| if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) { |
| SkPath path; |
| path.addOval(oval); |
| - this->internalDrawPath(target, useAA, path, stroke); |
| + this->internalDrawPath(target, paint, useAA, path, stroke); |
| } |
| } |
| @@ -1137,15 +1138,17 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok |
| AutoRestoreEffects are; |
| AutoCheckFlush acf(this); |
| GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf); |
| + GrDrawState* drawState = target->drawState(); |
| + |
| + bool useAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled(); |
| - bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled(); |
| if (useAA && stroke.getWidth() < 0 && !path.isConvex()) { |
| // Concave AA paths are expensive - try to avoid them for special cases |
| bool useVertexCoverage; |
| SkRect rects[2]; |
| if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { |
| - SkMatrix origViewMatrix = target->getDrawState().getViewMatrix(); |
| + SkMatrix origViewMatrix = drawState->getViewMatrix(); |
| GrDrawState::AutoViewMatrixRestore avmr; |
| if (!avmr.setIdentity(target->drawState())) { |
| return; |
| @@ -1164,12 +1167,32 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok |
| if (!isOval || path.isInverseFillType() |
| || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) { |
| - this->internalDrawPath(target, useAA, path, stroke); |
| + this->internalDrawPath(target, paint, useAA, path, stroke); |
| } |
| } |
| -void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path, |
| - const SkStrokeRec& stroke) { |
| +namespace { |
| +// See also: SkDrawTreatAsHairline. |
| +static inline bool should_convert_to_hairline(const GrPaint& paint, const SkStrokeRec& stroke, |
| + const SkMatrix& matrix, SkScalar* coverage) { |
| + |
| + if (stroke.getStyle() != SkStrokeRec::kStroke_Style) { |
| + return false; |
| + } |
| + |
| + SkASSERT(0 != stroke.getWidth()); |
| + |
| + if (!paint.isAntiAlias()) { |
|
bsalomon
2013/10/30 14:37:39
Currently GrContext tries to convert the GrPaint t
Kimmo Kinnunen
2013/11/01 14:56:19
Done.
|
| + return false; |
| + } |
| + |
| + return SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, coverage); |
| +} |
| +} |
| + |
| + |
| +void GrContext::internalDrawPath(GrDrawTarget* target, const GrPaint& paint, bool useAA, |
| + const SkPath& path, const SkStrokeRec& origStroke) { |
| SkASSERT(!path.isEmpty()); |
| // An Assumption here is that path renderer would use some form of tweaking |
| @@ -1183,22 +1206,35 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& |
| useAA = false; |
| } |
| + SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); |
| + // Can we treat a thin stroke as a hairline w/ coverage? If we can, we draw lots faster (raster |
| + // device does this same test). |
| + |
| + // Do not do this if gpu supports path rendering natively and we might be using the support (useAA == |
| + // false). Hairline renderer is likely to be slow due to program switches. |
| + if (useAA || !fGpu->caps()->pathRenderingSupport()) { |
| + SkScalar hairlineCoverage; |
| + if (should_convert_to_hairline(paint, *stroke, this->getMatrix(), &hairlineCoverage)) { |
| + target->drawState()->setCoverage(SkScalarRoundToInt(hairlineCoverage * paint.getCoverage())); |
| + stroke.writable()->setHairlineStyle(); |
| + } |
| + } |
| + |
| GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAntiAlias_DrawType : |
| GrPathRendererChain::kColor_DrawType; |
| const SkPath* pathPtr = &path; |
| SkPath tmpPath; |
| - SkStrokeRec strokeRec(stroke); |
| // Try a 1st time without stroking the path and without allowing the SW renderer |
| - GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type); |
| + GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type); |
| if (NULL == pr) { |
| - if (!strokeRec.isHairlineStyle()) { |
| + if (!stroke->isHairlineStyle()) { |
| // It didn't work the 1st time, so try again with the stroked path |
| - if (strokeRec.applyToPath(&tmpPath, *pathPtr)) { |
| + if (stroke->applyToPath(&tmpPath, *pathPtr)) { |
| pathPtr = &tmpPath; |
| - strokeRec.setFillStyle(); |
| + stroke.writable()->setFillStyle(); |
| } |
| } |
| if (pathPtr->isEmpty()) { |
| @@ -1206,7 +1242,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& |
| } |
| // This time, allow SW renderer |
| - pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type); |
| + pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type); |
| } |
| if (NULL == pr) { |
| @@ -1216,7 +1252,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& |
| return; |
| } |
| - pr->drawPath(*pathPtr, strokeRec, target, useAA); |
| + pr->drawPath(*pathPtr, *stroke, target, useAA); |
| } |
| //////////////////////////////////////////////////////////////////////////////// |