Index: src/gpu/GrDrawContext.cpp |
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp |
index 628b4b2fb2fd4cdeaadd8916dab97a3159d69061..12bb1dec2b47d0188ee25f95aed0e8925e4937b1 100644 |
--- a/src/gpu/GrDrawContext.cpp |
+++ b/src/gpu/GrDrawContext.cpp |
@@ -9,6 +9,7 @@ |
#include "GrBatchTest.h" |
#include "GrColor.h" |
#include "GrDrawContext.h" |
+#include "GrDrawContextPriv.h" |
#include "GrDrawingManager.h" |
#include "GrOvalRenderer.h" |
#include "GrPathRenderer.h" |
@@ -33,8 +34,11 @@ |
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext()) |
#define ASSERT_SINGLE_OWNER \ |
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) |
+#define ASSERT_SINGLE_OWNER_PRIV \ |
+ SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);) |
#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } |
#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; } |
+#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->abandoned()) { return false; } |
#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; } |
class AutoCheckFlush { |
@@ -250,6 +254,28 @@ static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { |
return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); |
} |
+GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint, |
+ const SkMatrix& viewMatrix, |
+ const SkRect& rect) { |
+ |
+ GrDrawBatch* batch = nullptr; |
+ if (should_apply_coverage_aa(paint, fRenderTarget)) { |
+ // The fill path can handle rotation but not skew. |
+ if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { |
+ SkRect devBoundRect; |
+ viewMatrix.mapRect(&devBoundRect, rect); |
+ batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix, |
+ rect, devBoundRect); |
+ } |
+ } else { |
+ // filled BW rect |
+ batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, |
+ nullptr, nullptr); |
+ } |
+ |
+ return batch; |
+} |
+ |
void GrDrawContext::drawRect(const GrClip& clip, |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
@@ -303,35 +329,28 @@ void GrDrawContext::drawRect(const GrClip& clip, |
bool snapToPixelCenters = false; |
SkAutoTUnref<GrDrawBatch> batch; |
- if (should_apply_coverage_aa(paint, fRenderTarget)) { |
- if (width >= 0) { |
+ if (width < 0) { |
+ batch.reset(this->getFillRectBatch(paint, viewMatrix, rect)); |
+ } else { |
+ GrColor color = paint.getColor(); |
+ |
+ if (should_apply_coverage_aa(paint, fRenderTarget)) { |
// The stroke path needs the rect to remain axis aligned (no rotation or skew). |
if (viewMatrix.rectStaysRect()) { |
- batch.reset(GrRectBatchFactory::CreateAAStroke(paint.getColor(), viewMatrix, rect, |
+ batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, |
*strokeInfo)); |
} |
} else { |
- // The fill path can handle rotation but not skew. |
- if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { |
- SkRect devBoundRect; |
- viewMatrix.mapRect(&devBoundRect, rect); |
- batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix, rect, |
- devBoundRect)); |
- } |
+ // 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. |
} |
- } else if (width >= 0) { |
- // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic |
- snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled()); |
- batch.reset(GrRectBatchFactory::CreateNonAAStroke(paint.getColor(), 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. |
- } else { |
- // filled BW rect |
- batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, |
- nullptr, nullptr)); |
} |
if (batch) { |
@@ -353,6 +372,39 @@ void GrDrawContext::drawRect(const GrClip& clip, |
strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); |
} |
+bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect, |
+ const GrStencilSettings& ss, |
+ SkRegion::Op op, |
+ bool invert, |
+ bool doAA, |
+ const SkMatrix& viewMatrix, |
+ const SkRect& rect) { |
+ ASSERT_SINGLE_OWNER_PRIV |
+ RETURN_FALSE_IF_ABANDONED_PRIV |
+ SkDEBUGCODE(fDrawContext->validate();) |
+ GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect"); |
+ |
+ AutoCheckFlush acf(fDrawContext->fDrawingManager); |
+ |
+ GrPaint paint; |
+ paint.setAntiAlias(doAA); |
+ paint.setCoverageSetOpXPFactory(op, invert); |
+ |
+ SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMatrix, rect)); |
+ if (batch) { |
+ GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, GrClip::WideOpen()); |
+ pipelineBuilder.setStencil(ss); |
+ |
+ fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch, scissorRect); |
+ return true; |
+ } |
+ |
+ SkPath path; |
+ path.setIsVolatile(true); |
+ path.addRect(rect); |
+ return this->drawAndStencilPath(scissorRect, ss, op, invert, doAA, viewMatrix, path); |
+} |
+ |
void GrDrawContext::fillRectToRect(const GrClip& clip, |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |
@@ -801,6 +853,80 @@ void GrDrawContext::drawPath(const GrClip& clip, |
this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
} |
+bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect, |
+ const GrStencilSettings& ss, |
+ SkRegion::Op op, |
+ bool invert, |
+ bool doAA, |
+ const SkMatrix& viewMatrix, |
+ const SkPath& path) { |
+ ASSERT_SINGLE_OWNER_PRIV |
+ RETURN_FALSE_IF_ABANDONED_PRIV |
+ SkDEBUGCODE(fDrawContext->validate();) |
+ GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath"); |
+ |
+ if (path.isEmpty() && path.isInverseFillType()) { |
+ this->drawAndStencilRect(scissorRect, ss, op, invert, false, SkMatrix::I(), |
+ SkRect::MakeIWH(fDrawContext->fRenderTarget->width(), |
+ fDrawContext->fRenderTarget->height())); |
+ return true; |
+ } |
+ |
+ AutoCheckFlush acf(fDrawContext->fDrawingManager); |
+ |
+ // 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 = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled(); |
+ bool isStencilDisabled = true; |
+ bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled(); |
+ |
+ const GrPathRendererChain::DrawType type = |
+ useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType |
+ : GrPathRendererChain::kColor_DrawType; |
+ |
+ GrPathRenderer::CanDrawPathArgs canDrawArgs; |
+ canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps(); |
+ canDrawArgs.fViewMatrix = &viewMatrix; |
+ canDrawArgs.fPath = &path; |
+ canDrawArgs.fStroke = &GrStrokeInfo::FillInfo(); |
+ canDrawArgs.fAntiAlias = useCoverageAA; |
+ canDrawArgs.fIsStencilDisabled = isStencilDisabled; |
+ canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA; |
+ |
+ // Don't allow the SW renderer |
+ GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type); |
+ if (!pr) { |
+ return false; |
+ } |
+ |
+ GrPaint paint; |
+ paint.setCoverageSetOpXPFactory(op, invert); |
+ |
+ // TODO: it is unfortunate that we have to convert this to a GrClip to |
+ // call drawPath. |
+ GrClip clip; |
+ if (scissorRect) { |
+ clip.setIRect(*scissorRect); |
+ } |
+ |
+ GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, clip); |
+ pipelineBuilder.setStencil(ss); |
+ |
+ GrPathRenderer::DrawPathArgs args; |
+ args.fTarget = fDrawContext->getDrawTarget(); |
+ args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider(); |
+ args.fPipelineBuilder = &pipelineBuilder; |
+ args.fColor = GrColor_WHITE; |
+ args.fViewMatrix = &viewMatrix; |
+ args.fPath = &path; |
+ args.fStroke = &GrStrokeInfo::FillInfo(); |
+ args.fAntiAlias = useCoverageAA; |
+ pr->drawPath(args); |
+ return true; |
+} |
+ |
void GrDrawContext::internalDrawPath(const GrClip& clip, |
const GrPaint& paint, |
const SkMatrix& viewMatrix, |