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); |
} |
//////////////////////////////////////////////////////////////////////////////// |