Index: src/gpu/GrDrawContext.cpp |
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp |
index a7c7f6ae5f4df8e99836ba6e50b2b9793f71b2d8..6c80f52bba5c9260e815fed142a708bd1e0708d1 100644 |
--- a/src/gpu/GrDrawContext.cpp |
+++ b/src/gpu/GrDrawContext.cpp |
@@ -279,22 +279,18 @@ |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
const SkRect& rect, |
- const GrStyle* style) { |
- if (!style) { |
- style = &GrStyle::SimpleFill(); |
- } |
+ const GrStrokeInfo* strokeInfo) { |
ASSERT_SINGLE_OWNER |
RETURN_IF_ABANDONED |
SkDEBUGCODE(this->validate();) |
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect"); |
- // Path effects should've been devolved to a path in SkGpuDevice |
- SkASSERT(!style->pathEffect()); |
- |
- AutoCheckFlush acf(fDrawingManager); |
- |
- const SkStrokeRec& stroke = style->strokeRec(); |
- SkScalar width = stroke.getWidth(); |
+ // Dashing should've been devolved to a path in SkGpuDevice |
+ SkASSERT(!strokeInfo || !strokeInfo->isDashed()); |
+ |
+ AutoCheckFlush acf(fDrawingManager); |
+ |
+ SkScalar width = !strokeInfo ? -1 : strokeInfo->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. |
@@ -341,7 +337,7 @@ |
// 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)); |
+ *strokeInfo)); |
} |
} else { |
// Non-AA hairlines are snapped to pixel centers to make which pixels are hit |
@@ -371,7 +367,8 @@ |
SkPath path; |
path.setIsVolatile(true); |
path.addRect(rect); |
- this->internalDrawPath(clip, paint, viewMatrix, path, *style); |
+ this->internalDrawPath(clip, paint, viewMatrix, path, |
+ strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); |
} |
bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect, |
@@ -539,7 +536,7 @@ |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
const SkRRect& rrect, |
- const GrStyle& style) { |
+ const GrStrokeInfo& strokeInfo) { |
ASSERT_SINGLE_OWNER |
RETURN_IF_ABANDONED |
SkDEBUGCODE(this->validate();) |
@@ -549,8 +546,8 @@ |
return; |
} |
- SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice |
- const SkStrokeRec stroke = style.strokeRec(); |
+ SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice |
+ |
AutoCheckFlush acf(fDrawingManager); |
if (should_apply_coverage_aa(paint, fRenderTarget.get())) { |
@@ -559,7 +556,7 @@ |
SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(), |
viewMatrix, |
rrect, |
- stroke, |
+ strokeInfo, |
shaderCaps)); |
if (batch) { |
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip); |
@@ -571,7 +568,7 @@ |
SkPath path; |
path.setIsVolatile(true); |
path.addRRect(rrect); |
- this->internalDrawPath(clip, paint, viewMatrix, path, style); |
+ this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
} |
bool GrDrawContext::drawFilledDRRect(const GrClip& clip, |
@@ -657,7 +654,7 @@ |
path.setFillType(SkPath::kEvenOdd_FillType); |
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip); |
- this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill()); |
+ this->internalDrawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo()); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -666,7 +663,7 @@ |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
const SkRect& oval, |
- const GrStyle& style) { |
+ const GrStrokeInfo& strokeInfo) { |
ASSERT_SINGLE_OWNER |
RETURN_IF_ABANDONED |
SkDEBUGCODE(this->validate();) |
@@ -676,16 +673,16 @@ |
return; |
} |
- SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice |
- |
- AutoCheckFlush acf(fDrawingManager); |
- const SkStrokeRec& stroke = style.strokeRec(); |
+ SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice |
+ |
+ AutoCheckFlush acf(fDrawingManager); |
+ |
if (should_apply_coverage_aa(paint, fRenderTarget.get())) { |
GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); |
SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(), |
viewMatrix, |
oval, |
- stroke, |
+ strokeInfo, |
shaderCaps)); |
if (batch) { |
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip); |
@@ -697,7 +694,7 @@ |
SkPath path; |
path.setIsVolatile(true); |
path.addOval(oval); |
- this->internalDrawPath(clip, paint, viewMatrix, path, style); |
+ this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
} |
void GrDrawContext::drawImageNine(const GrClip& clip, |
@@ -724,7 +721,11 @@ |
// Can 'path' be drawn as a pair of filled nested rectangles? |
-static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) { |
+static bool is_nested_rects(const SkMatrix& viewMatrix, |
+ const SkPath& path, |
+ const SkStrokeRec& stroke, |
+ SkRect rects[2]) { |
+ SkASSERT(stroke.isFillStyle()); |
if (path.isInverseFillType()) { |
return false; |
@@ -798,7 +799,7 @@ |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
const SkPath& path, |
- const GrStyle& style) { |
+ const GrStrokeInfo& strokeInfo) { |
ASSERT_SINGLE_OWNER |
RETURN_IF_ABANDONED |
SkDEBUGCODE(this->validate();) |
@@ -813,12 +814,12 @@ |
AutoCheckFlush acf(fDrawingManager); |
- if (should_apply_coverage_aa(paint, fRenderTarget.get()) && !style.pathEffect()) { |
- if (style.isSimpleFill() && !path.isConvex()) { |
+ if (should_apply_coverage_aa(paint, fRenderTarget.get()) && !strokeInfo.isDashed()) { |
+ if (strokeInfo.getWidth() < 0 && !path.isConvex()) { |
// Concave AA paths are expensive - try to avoid them for special cases |
SkRect rects[2]; |
- if (fills_as_nested_rects(viewMatrix, path, rects)) { |
+ if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) { |
SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects( |
paint.getColor(), viewMatrix, rects)); |
if (batch) { |
@@ -836,7 +837,7 @@ |
SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(), |
viewMatrix, |
ovalRect, |
- style.strokeRec(), |
+ strokeInfo, |
shaderCaps)); |
if (batch) { |
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get(), clip); |
@@ -851,7 +852,7 @@ |
// cache. This presents a potential hazard for buffered drawing. However, |
// the writePixels that uploads to the scratch will perform a flush so we're |
// OK. |
- this->internalDrawPath(clip, paint, viewMatrix, path, style); |
+ this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
} |
bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect, |
@@ -891,7 +892,7 @@ |
canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps(); |
canDrawArgs.fViewMatrix = &viewMatrix; |
canDrawArgs.fPath = &path; |
- canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
+ canDrawArgs.fStroke = &GrStrokeInfo::FillInfo(); |
canDrawArgs.fAntiAlias = useCoverageAA; |
canDrawArgs.fIsStencilDisabled = isStencilDisabled; |
canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA; |
@@ -922,7 +923,7 @@ |
args.fColor = GrColor_WHITE; |
args.fViewMatrix = &viewMatrix; |
args.fPath = &path; |
- args.fStyle = &GrStyle::SimpleFill(); |
+ args.fStroke = &GrStrokeInfo::FillInfo(); |
args.fAntiAlias = useCoverageAA; |
args.fGammaCorrect = fDrawContext->isGammaCorrect(); |
pr->drawPath(args); |
@@ -932,12 +933,16 @@ |
void GrDrawContext::internalDrawPath(const GrClip& clip, |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
- const SkPath& origPath, |
- const GrStyle& origStyle) { |
- ASSERT_SINGLE_OWNER |
- RETURN_IF_ABANDONED |
- SkASSERT(!origPath.isEmpty()); |
- |
+ const SkPath& path, |
+ const GrStrokeInfo& strokeInfo) { |
+ ASSERT_SINGLE_OWNER |
+ RETURN_IF_ABANDONED |
+ SkASSERT(!path.isEmpty()); |
+ |
+ // An Assumption here is that path renderer would use some form of tweaking |
+ // the src color (either the input alpha or in the frag shader) to implement |
+ // aa. If we have some future driver-mojo path AA that can do the right |
+ // thing WRT to the blend then we'll need some query on the PR. |
bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get()); |
const bool isStencilDisabled = true; |
bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled(); |
@@ -946,65 +951,61 @@ |
useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType |
: GrPathRendererChain::kColor_DrawType; |
+ const SkPath* pathPtr = &path; |
SkTLazy<SkPath> tmpPath; |
- SkTLazy<GrStyle> tmpStyle; |
+ const GrStrokeInfo* strokeInfoPtr = &strokeInfo; |
GrPathRenderer::CanDrawPathArgs canDrawArgs; |
canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps(); |
canDrawArgs.fViewMatrix = &viewMatrix; |
- canDrawArgs.fPath = &origPath; |
- canDrawArgs.fStyle = &origStyle; |
+ canDrawArgs.fPath = pathPtr; |
+ canDrawArgs.fStroke = strokeInfoPtr; |
canDrawArgs.fAntiAlias = useCoverageAA; |
canDrawArgs.fIsStencilDisabled = isStencilDisabled; |
canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA; |
- // Try a 1st time without applying any of the style to the geometry (and barring sw) |
+ // Try a 1st time without stroking the path and without allowing the SW renderer |
GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type); |
- SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix); |
- |
- if (!pr && canDrawArgs.fStyle->pathEffect()) { |
- // It didn't work above, so try again with the path effect applied. |
- SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); |
- if (!canDrawArgs.fStyle->applyPathEffectToPath(tmpPath.init(), &rec, *canDrawArgs.fPath, |
- styleScale)) { |
- GrStyle noPathEffect(canDrawArgs.fStyle->strokeRec(), nullptr); |
- this->internalDrawPath(clip, paint, viewMatrix, *canDrawArgs.fPath, noPathEffect); |
+ |
+ GrStrokeInfo dashlessStrokeInfo(strokeInfo, false); |
+ if (nullptr == pr && strokeInfo.isDashed()) { |
+ // It didn't work above, so try again with dashed stroke converted to a dashless stroke. |
+ if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) { |
return; |
} |
- tmpStyle.init(rec, nullptr); |
- canDrawArgs.fPath = tmpPath.get(); |
- canDrawArgs.fStyle = tmpStyle.get(); |
- if (canDrawArgs.fPath->isEmpty()) { |
+ pathPtr = tmpPath.get(); |
+ if (pathPtr->isEmpty()) { |
return; |
} |
+ strokeInfoPtr = &dashlessStrokeInfo; |
+ |
+ canDrawArgs.fPath = pathPtr; |
+ canDrawArgs.fStroke = strokeInfoPtr; |
pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type); |
} |
- if (!pr) { |
- SkASSERT(!canDrawArgs.fStyle->pathEffect()); |
- if (canDrawArgs.fStyle->strokeRec().needToApply()) { |
+ |
+ if (nullptr == pr) { |
+ if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) && |
+ !strokeInfoPtr->isFillStyle()) { |
+ // It didn't work above, so try again with stroke converted to a fill. |
if (!tmpPath.isValid()) { |
tmpPath.init(); |
} |
- // It didn't work above, so try again by applying the stroke to the geometry. |
- SkStrokeRec::InitStyle fillOrHairline; |
- if (!canDrawArgs.fStyle->applyToPath(tmpPath.get(), &fillOrHairline, |
- *canDrawArgs.fPath, styleScale)) { |
+ dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale())); |
+ if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) { |
return; |
} |
- if (!tmpStyle.isValid()) { |
- tmpStyle.init(fillOrHairline); |
- } else { |
- tmpStyle.get()->resetToInitStyle(fillOrHairline); |
- } |
- canDrawArgs.fPath = tmpPath.get(); |
- canDrawArgs.fStyle = tmpStyle.get(); |
- if (canDrawArgs.fPath->isEmpty()) { |
+ pathPtr = tmpPath.get(); |
+ if (pathPtr->isEmpty()) { |
return; |
} |
- |
- pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type); |
- } |
+ dashlessStrokeInfo.setFillStyle(); |
+ strokeInfoPtr = &dashlessStrokeInfo; |
+ } |
+ |
+ canDrawArgs.fPath = pathPtr; |
+ canDrawArgs.fStroke = strokeInfoPtr; |
// This time, allow SW renderer |
pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type); |
@@ -1025,8 +1026,8 @@ |
args.fPipelineBuilder = &pipelineBuilder; |
args.fColor = paint.getColor(); |
args.fViewMatrix = &viewMatrix; |
- args.fPath = canDrawArgs.fPath; |
- args.fStyle = canDrawArgs.fStyle; |
+ args.fPath = pathPtr; |
+ args.fStroke = strokeInfoPtr; |
args.fAntiAlias = useCoverageAA; |
args.fGammaCorrect = this->isGammaCorrect(); |
pr->drawPath(args); |