diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 12 | ||||
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.h | 9 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.cpp | 14 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.h | 6 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 123 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 12 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 18 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.cpp | 38 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.h | 15 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 111 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.cpp | 9 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.cpp | 15 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.h | 9 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverPathRenderer.cpp | 22 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverPathRenderer.h | 12 |
15 files changed, 225 insertions, 200 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index a8af559991..0a11661eba 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -605,12 +605,11 @@ GrEffectRef* QuadEdgeEffect::TestCreate(SkRandom* random, /////////////////////////////////////////////////////////////////////////////// -bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrAAConvexPathRenderer::canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const { return (target->caps()->shaderDerivativeSupport() && antiAlias && - stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()); + stroke.isFillStyle() && !this->path().isInverseFillType() && this->path().isConvex()); } namespace { @@ -623,12 +622,11 @@ extern const GrVertexAttrib gPathAttribs[] = { }; -bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, - const SkStrokeRec&, +bool GrAAConvexPathRenderer::onDrawPath(const SkStrokeRec&, GrDrawTarget* target, bool antiAlias) { - const SkPath* path = &origPath; + const SkPath* path = &this->path(); if (path->isEmpty()) { return true; } @@ -645,7 +643,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, // segment representation. SkPath tmpPath; if (viewMatrix.hasPerspective()) { - origPath.transform(viewMatrix, &tmpPath); + this->path().transform(viewMatrix, &tmpPath); path = &tmpPath; viewMatrix = SkMatrix::I(); } diff --git a/src/gpu/GrAAConvexPathRenderer.h b/src/gpu/GrAAConvexPathRenderer.h index 62394a3a74..61e5472ca7 100644 --- a/src/gpu/GrAAConvexPathRenderer.h +++ b/src/gpu/GrAAConvexPathRenderer.h @@ -13,14 +13,15 @@ class GrAAConvexPathRenderer : public GrPathRenderer { public: GrAAConvexPathRenderer(); - virtual bool canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + virtual bool canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const SK_OVERRIDE; protected: - virtual bool onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + virtual bool onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) SK_OVERRIDE; + +private: + typedef GrPathRenderer INHERITED; }; diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 830f513e6c..7f152661f1 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -826,8 +826,7 @@ bool GrAAHairLinePathRenderer::createBezierGeom( return true; } -bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrAAHairLinePathRenderer::canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const { if (!antiAlias) { @@ -840,7 +839,7 @@ bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, return false; } - if (SkPath::kLine_SegmentMask == path.getSegmentMasks() || + if (SkPath::kLine_SegmentMask == this->path().getSegmentMasks() || target->caps()->shaderDerivativeSupport()) { return true; } @@ -884,8 +883,7 @@ bool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertice return true; } -bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrAAHairLinePathRenderer::onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { GrDrawState* drawState = target->drawState(); @@ -910,7 +908,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, PREALLOC_PTARRAY(128) conics; IntArray qSubdivs; FloatArray cWeights; - quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClipBounds, + quadCnt = generate_lines_and_quads(this->path(), drawState->getViewMatrix(), devClipBounds, &lines, &quads, &conics, &qSubdivs, &cWeights); lineCnt = lines.count() / 2; conicCnt = conics.count() / 3; @@ -920,7 +918,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, GrDrawTarget::AutoReleaseGeometry arg; SkRect devBounds; - if (!this->createLineGeom(path, + if (!this->createLineGeom(this->path(), target, lines, lineCnt, @@ -966,7 +964,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, GrDrawTarget::AutoReleaseGeometry arg; SkRect devBounds; - if (!this->createBezierGeom(path, + if (!this->createBezierGeom(this->path(), target, quads, quadCnt, diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h index 22cc876eab..627474abdb 100644 --- a/src/gpu/GrAAHairLinePathRenderer.h +++ b/src/gpu/GrAAHairLinePathRenderer.h @@ -17,8 +17,7 @@ public: static GrPathRenderer* Create(GrContext* context); - virtual bool canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + virtual bool canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const SK_OVERRIDE; @@ -27,8 +26,7 @@ public: typedef SkTArray<float, true> FloatArray; protected: - virtual bool onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + virtual bool onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) SK_OVERRIDE; diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index caee6eb033..35e0818dd0 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -30,12 +30,11 @@ typedef SkClipStack::Element Element; using namespace GrReducedClip; //////////////////////////////////////////////////////////////////////////////// -namespace { // set up the draw state to enable the aa clipping mask. Besides setting up the // stage matrix this also alters the vertex layout -void setup_drawstate_aaclip(GrGpu* gpu, - GrTexture* result, - const SkIRect &devBound) { +static void setup_drawstate_aaclip(GrGpu* gpu, + GrTexture* result, + const SkIRect &devBound) { GrDrawState* drawState = gpu->drawState(); SkASSERT(drawState); @@ -59,24 +58,21 @@ void setup_drawstate_aaclip(GrGpu* gpu, kPosition_GrCoordSet))->unref(); } -bool path_needs_SW_renderer(GrContext* context, - GrGpu* gpu, - const SkPath& origPath, - const SkStrokeRec& stroke, - bool doAA) { - // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer - SkTCopyOnFirstWrite<SkPath> path(origPath); - if (path->isInverseFillType()) { - path.writable()->toggleInverseFillType(); - } - // last (false) parameter disallows use of the SW path renderer +static bool path_needs_SW_renderer(GrContext* context, + GrGpu* gpu, + const SkPath& origPath, + const SkStrokeRec& stroke, + bool doAA) { GrPathRendererChain::DrawType type = doAA ? GrPathRendererChain::kColorAntiAlias_DrawType : GrPathRendererChain::kColor_DrawType; + // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer + SkPath::FillType fillType = SkPath::ConvertToNonInverseFillType(origPath.getFillType()); - return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); -} - + // the 'false' parameter disallows use of the SW path renderer + GrPathRenderer::AutoClearPath acp(context->getPathRenderer(origPath, stroke, gpu, + false, type, fillType)); + return NULL == acp.renderer(); } /* @@ -313,9 +309,20 @@ void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { } //////////////////////////////////////////////////////////////////////////////// +bool GrClipMaskManager::drawFilledPath(GrTexture* target, + GrPathRenderer* pathRenderer, + bool isAA) { + GrDrawState* drawState = fGpu->drawState(); + + drawState->setRenderTarget(target->asRenderTarget()); + + SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); + pathRenderer->drawPath(stroke, fGpu, isAA); + return true; +} + bool GrClipMaskManager::drawElement(GrTexture* target, - const SkClipStack::Element* element, - GrPathRenderer* pr) { + const SkClipStack::Element* element) { GrDrawState* drawState = fGpu->drawState(); drawState->setRenderTarget(target->asRenderTarget()); @@ -336,21 +343,19 @@ bool GrClipMaskManager::drawElement(GrTexture* target, } return true; case Element::kPath_Type: { - SkTCopyOnFirstWrite<SkPath> path(element->getPath()); - if (path->isInverseFillType()) { - path.writable()->toggleInverseFillType(); - } SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); - if (NULL == pr) { - GrPathRendererChain::DrawType type; - type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : - GrPathRendererChain::kColor_DrawType; - pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); - } - if (NULL == pr) { + GrPathRendererChain::DrawType type; + type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; + SkPath::FillType fillType = element->getPath().getFillType(); + GrPathRenderer::AutoClearPath acp(this->getContext()->getPathRenderer( + element->getPath(), + stroke, fGpu, false, type, + SkPath::ConvertToNonInverseFillType(fillType))); + if (NULL == acp.renderer()) { return false; } - pr->drawPath(element->getPath(), stroke, fGpu, element->isAA()); + acp->drawPath(stroke, fGpu, element->isAA()); break; } default: @@ -363,7 +368,7 @@ bool GrClipMaskManager::drawElement(GrTexture* target, bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element* element, - GrPathRenderer** pr) { + GrPathRenderer::AutoClearPath* acp) { GrDrawState* drawState = fGpu->drawState(); drawState->setRenderTarget(target->asRenderTarget()); @@ -371,16 +376,15 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, case Element::kRect_Type: return true; case Element::kPath_Type: { - SkTCopyOnFirstWrite<SkPath> path(element->getPath()); - if (path->isInverseFillType()) { - path.writable()->toggleInverseFillType(); - } SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); GrPathRendererChain::DrawType type = element->isAA() ? GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : GrPathRendererChain::kStencilAndColor_DrawType; - *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); - return NULL != *pr; + SkPath::FillType fillType = element->getPath().getFillType(); + acp->set(this->getContext()->getPathRenderer(element->getPath(), + stroke, fGpu, false, type, + SkPath::ConvertToNonInverseFillType(fillType))); + return NULL != acp->renderer(); } default: // something is wrong if we're trying to draw an empty element. @@ -525,8 +529,8 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, bool invert = element->isInverseFilled(); if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { - GrPathRenderer* pr = NULL; - bool useTemp = !this->canStencilAndDrawElement(result, element, &pr); + GrPathRenderer::AutoClearPath acp; + bool useTemp = !this->canStencilAndDrawElement(result, element, &acp); GrTexture* dst; // This is the bounds of the clip element in the space of the alpha-mask. The temporary // mask buffer can be substantially larger than the actually clip stack element. We @@ -573,9 +577,13 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, drawState->setAlpha(invert ? 0x00 : 0xff); - if (!this->drawElement(dst, element, pr)) { - fAACache.reset(); - return NULL; + if (NULL != acp.renderer()) { + this->drawFilledPath(dst, acp.renderer(), element->isAA()); + } else { + if (!this->drawElement(dst, element)) { + fAACache.reset(); + return NULL; + } } if (useTemp) { @@ -601,7 +609,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, drawState->disableStencil(); } } else { - // all the remaining ops can just be directly draw into the accumulation buffer + // all the remaining ops can just be directly drawn into the accumulation buffer drawState->setAlpha(0xff); setup_boolean_blendcoeffs(drawState, op); this->drawElement(result, element); @@ -687,25 +695,22 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, SkRegion::Op op = element->getOp(); - GrPathRenderer* pr = NULL; - SkTCopyOnFirstWrite<SkPath> clipPath; + GrPathRenderer::AutoClearPath acp; if (Element::kRect_Type == element->getType()) { stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; fillInverted = false; } else { SkASSERT(Element::kPath_Type == element->getType()); - clipPath.init(element->getPath()); - fillInverted = clipPath->isInverseFillType(); - if (fillInverted) { - clipPath.writable()->toggleInverseFillType(); - } - pr = this->getContext()->getPathRenderer(*clipPath, + fillInverted = element->getPath().isInverseFillType(); + SkPath::FillType fill = element->getPath().getFillType(); + acp.set(this->getContext()->getPathRenderer(element->getPath(), stroke, fGpu, false, GrPathRendererChain::kStencilOnly_DrawType, - &stencilSupport); - if (NULL == pr) { + SkPath::ConvertToNonInverseFillType(fill), + &stencilSupport)); + if (NULL == acp.renderer()) { return false; } } @@ -741,12 +746,12 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, fGpu->drawSimpleRect(element->getRect(), NULL); } else { SkASSERT(Element::kPath_Type == element->getType()); - if (!clipPath->isEmpty()) { + if (NULL != acp.renderer()) { if (canRenderDirectToStencil) { *drawState->stencil() = gDrawToStencil; - pr->drawPath(*clipPath, stroke, fGpu, false); + acp->drawPath(stroke, fGpu, false); } else { - pr->stencilPath(*clipPath, stroke, fGpu); + acp->stencilPath(stroke, fGpu); } } } @@ -764,7 +769,7 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, } else { SkASSERT(Element::kPath_Type == element->getType()); SET_RANDOM_COLOR - pr->drawPath(*clipPath, stroke, fGpu, false); + acp->drawPath(stroke, fGpu, false); } } else { SET_RANDOM_COLOR diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index f44a8e7b22..fa54f3ce0e 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -11,6 +11,7 @@ #include "GrClipMaskCache.h" #include "GrContext.h" #include "GrDrawState.h" +#include "GrPathRenderer.h" #include "GrReducedClip.h" #include "GrStencil.h" #include "GrTexture.h" @@ -130,15 +131,18 @@ private: bool useSWOnlyPath(const GrReducedClip::ElementList& elements); + // Draws a filled clip path into the target alpha mask + bool drawFilledPath(GrTexture* target, GrPathRenderer* pathRenderer, bool isAA); + // Draws a clip element into the target alpha mask. The caller should have already setup the - // desired blend operation. Optionally if the caller already selected a path renderer it can - // be passed. Otherwise the function will select one if the element is a path. - bool drawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer* = NULL); + // desired blend operation. + bool drawElement(GrTexture* target, const SkClipStack::Element* element); // Determines whether it is possible to draw the element to both the stencil buffer and the // alpha mask simultaneously. If so and the element is a path a compatible path renderer is // also returned. - bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer**); + bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*, + GrPathRenderer::AutoClearPath* pr); void mergeMask(GrTexture* dstMask, GrTexture* srcMask, diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index bb0f4fa9fa..ab20dc3902 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1148,16 +1148,18 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& GrPathRendererChain::DrawType type = useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : - GrPathRendererChain::kColor_DrawType; + GrPathRendererChain::kColor_DrawType; const SkPath* pathPtr = &path; SkTLazy<SkPath> tmpPath; SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); // Try a 1st time without stroking the path and without allowing the SW renderer - GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type); + GrPathRenderer::AutoClearPath acp(this->getPathRenderer(*pathPtr, *stroke, + target, false, type, + pathPtr->getFillType())); - if (NULL == pr) { + if (NULL == acp.renderer()) { if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, this->getMatrix(), NULL)) { // It didn't work the 1st time, so try again with the stroked path if (stroke->applyToPath(tmpPath.init(), *pathPtr)) { @@ -1170,17 +1172,18 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& } // This time, allow SW renderer - pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type); + acp.set(this->getPathRenderer(*pathPtr, *stroke, target, true, type, + pathPtr->getFillType())); } - if (NULL == pr) { + if (NULL == acp.renderer()) { #ifdef SK_DEBUG GrPrintf("Unable to find path renderer compatible with path.\n"); #endif return; } - pr->drawPath(*pathPtr, *stroke, target, useCoverageAA); + acp->drawPath(*stroke, target, useCoverageAA); } //////////////////////////////////////////////////////////////////////////////// @@ -1676,6 +1679,7 @@ GrPathRenderer* GrContext::getPathRenderer(const SkPath& path, const GrDrawTarget* target, bool allowSW, GrPathRendererChain::DrawType drawType, + SkPath::FillType fillType, GrPathRendererChain::StencilSupport* stencilSupport) { if (NULL == fPathRendererChain) { @@ -1686,6 +1690,7 @@ GrPathRenderer* GrContext::getPathRenderer(const SkPath& path, stroke, target, drawType, + fillType, stencilSupport); if (NULL == pr && allowSW) { @@ -1693,6 +1698,7 @@ GrPathRenderer* GrContext::getPathRenderer(const SkPath& path, fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); } pr = fSoftwarePathRenderer; + pr->setPath(path, fillType); } return pr; diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 1f20ac2724..69da9d9bf2 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -163,10 +163,9 @@ static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& strok } GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport( - const SkPath& path, const SkStrokeRec& stroke, const GrDrawTarget*) const { - if (single_pass_path(path, stroke)) { + if (single_pass_path(this->path(), stroke)) { return GrPathRenderer::kNoRestriction_StencilSupport; } else { return GrPathRenderer::kStencilOnly_StencilSupport; @@ -325,8 +324,7 @@ FINISHED: return true; } -bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, - const SkStrokeRec& origStroke, +bool GrDefaultPathRenderer::internalDrawPath(const SkStrokeRec& origStroke, GrDrawTarget* target, bool stencilOnly) { @@ -346,13 +344,13 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, } SkScalar tol = SK_Scalar1; - tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); + tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, this->path().getBounds()); int vertexCnt; int indexCnt; GrPrimitiveType primType; GrDrawTarget::AutoReleaseGeometry arg; - if (!this->createGeom(path, + if (!this->createGeom(this->path(), *stroke, tol, target, @@ -386,7 +384,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, lastPassIsBounds = false; drawFace[0] = GrDrawState::kBoth_DrawFace; } else { - if (single_pass_path(path, *stroke)) { + if (single_pass_path(this->path(), *stroke)) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; @@ -396,7 +394,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, drawFace[0] = GrDrawState::kBoth_DrawFace; lastPassIsBounds = false; } else { - switch (path.getFillType()) { + switch (this->path().getFillType()) { case SkPath::kInverseEvenOdd_FillType: reverse = true; // fallthrough @@ -463,7 +461,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, } SkRect devBounds; - GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds); + GetPathDevBounds(this->path(), drawState->getRenderTarget(), viewM, &devBounds); for (int p = 0; p < passCount; ++p) { drawState->setDrawFace(drawFace[p]); @@ -490,7 +488,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, avmr.setIdentity(drawState); } } else { - bounds = path.getBounds(); + bounds = this->path().getBounds(); } GrDrawTarget::AutoGeometryAndStatePush agasp(target, GrDrawTarget::kPreserve_ASRInit); target->drawSimpleRect(bounds, NULL); @@ -509,8 +507,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, return true; } -bool GrDefaultPathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrDefaultPathRenderer::canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const { // this class can draw any path with any fill but doesn't do any anti-aliasing. @@ -520,20 +517,15 @@ bool GrDefaultPathRenderer::canDrawPath(const SkPath& path, IsStrokeHairlineOrEquivalent(stroke, target->getDrawState().getViewMatrix(), NULL)); } -bool GrDefaultPathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrDefaultPathRenderer::onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { - return this->internalDrawPath(path, - stroke, - target, - false); + return this->internalDrawPath(stroke, target, false); } -void GrDefaultPathRenderer::onStencilPath(const SkPath& path, - const SkStrokeRec& stroke, +void GrDefaultPathRenderer::onStencilPath(const SkStrokeRec& stroke, GrDrawTarget* target) { - SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); - SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); - this->internalDrawPath(path, stroke, target, true); + SkASSERT(SkPath::kInverseEvenOdd_FillType != this->path().getFillType()); + SkASSERT(SkPath::kInverseWinding_FillType != this->path().getFillType()); + this->internalDrawPath(stroke, target, true); } diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h index c60afccbfb..56d4370718 100644 --- a/src/gpu/GrDefaultPathRenderer.h +++ b/src/gpu/GrDefaultPathRenderer.h @@ -19,28 +19,23 @@ class SK_API GrDefaultPathRenderer : public GrPathRenderer { public: GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport); - virtual bool canDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool canDrawPath(const SkStrokeRec&, const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; private: - virtual StencilSupport onGetStencilSupport(const SkPath&, - const SkStrokeRec&, + virtual StencilSupport onGetStencilSupport(const SkStrokeRec&, const GrDrawTarget*) const SK_OVERRIDE; - virtual bool onDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool onDrawPath(const SkStrokeRec&, GrDrawTarget*, bool antiAlias) SK_OVERRIDE; - virtual void onStencilPath(const SkPath&, - const SkStrokeRec&, + virtual void onStencilPath(const SkStrokeRec&, GrDrawTarget*) SK_OVERRIDE; - bool internalDrawPath(const SkPath&, - const SkStrokeRec&, + bool internalDrawPath(const SkStrokeRec&, GrDrawTarget*, bool stencilOnly); diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index 88665c1d42..692cefc7f1 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -74,70 +74,108 @@ public: GrPathRendererChain::kNoRestriction_StencilSupport; /** - * This function is to get the stencil support for a particular path. The path's fill must + * This function is to get the stencil support for the current path. The path's fill must * not be an inverse type. * - * @param target target that the path will be rendered to - * @param path the path that will be drawn * @param stroke the stroke information (width, join, cap). + * @param target target that the path will be rendered to */ - StencilSupport getStencilSupport(const SkPath& path, - const SkStrokeRec& stroke, + StencilSupport getStencilSupport(const SkStrokeRec& stroke, const GrDrawTarget* target) const { - SkASSERT(!path.isInverseFillType()); - return this->onGetStencilSupport(path, stroke, target); + SkASSERT(!fPath.isInverseFillType()); + return this->onGetStencilSupport(stroke, target); + } + + // Set the path and fill type the path renderer is to use. + // 'fillType' is included as a parameter b.c. we often want to draw + // inverse filled paths normally filled. + void setPath(const SkPath& path, SkPath::FillType fillType) { + SkASSERT(fPath.isEmpty()); + fPath = path; + fPath.setFillType(fillType); + } + + void resetPath() { + fPath.reset(); } /** - * Returns true if this path renderer is able to render the path. Returning false allows the - * caller to fallback to another path renderer This function is called when searching for a path - * renderer capable of rendering a path. + * Returns true if this path renderer is able to render the current path. Returning false + * allows the caller to fallback to another path renderer This function is called when + * searching for a path renderer capable of rendering a path. * - * @param path The path to draw * @param stroke The stroke information (width, join, cap) * @param target The target that the path will be rendered to * @param antiAlias True if anti-aliasing is required. * * @return true if the path can be drawn by this object, false otherwise. */ - virtual bool canDrawPath(const SkPath& path, - const SkStrokeRec& rec, + virtual bool canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const = 0; /** - * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then - * the subclass must respect the stencil settings of the target's draw state. + * Draws the current path into the draw target. If getStencilSupport() would return + * kNoRestriction then the subclass must respect the stencil settings of the + * target's draw state. * - * @param path the path to draw. * @param stroke the stroke information (width, join, cap) * @param target target that the path will be rendered to * @param antiAlias true if anti-aliasing is required. */ - bool drawPath(const SkPath& path, - const SkStrokeRec& stroke, + bool drawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { - SkASSERT(!path.isEmpty()); - SkASSERT(this->canDrawPath(path, stroke, target, antiAlias)); + SkASSERT(!fPath.isEmpty()); + SkASSERT(this->canDrawPath(stroke, target, antiAlias)); SkASSERT(target->drawState()->getStencil().isDisabled() || - kNoRestriction_StencilSupport == this->getStencilSupport(path, stroke, target)); - return this->onDrawPath(path, stroke, target, antiAlias); + kNoRestriction_StencilSupport == this->getStencilSupport(stroke, target)); + return this->onDrawPath(stroke, target, antiAlias); } /** - * Draws the path to the stencil buffer. Assume the writable stencil bits are already - * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards. + * Draws the current path to the stencil buffer. Assume the writable stencil bits are already + * initialized to zero. The pixels inside the path will have non-zero stencil values + * afterwards. * - * @param path the path to draw. * @param stroke the stroke information (width, join, cap) * @param target target that the path will be rendered to */ - void stencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) { - SkASSERT(!path.isEmpty()); - SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target)); - this->onStencilPath(path, stroke, target); + void stencilPath(const SkStrokeRec& stroke, GrDrawTarget* target) { + SkASSERT(!fPath.isEmpty()); + SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(stroke, target)); + this->onStencilPath(stroke, target); } + class AutoClearPath : ::SkNoncopyable { + public: + AutoClearPath(GrPathRenderer* renderer) : fRenderer(renderer) {} + AutoClearPath() : fRenderer(NULL) {} + ~AutoClearPath() { + this->reset(); + } + + GrPathRenderer* renderer() { + return fRenderer; + } + + void set(GrPathRenderer* renderer) { + this->reset(); + fRenderer = renderer; + } + + GrPathRenderer* operator->() { return fRenderer; } + + private: + void reset() { + if (NULL != fRenderer) { + fRenderer->resetPath(); + } + fRenderer = NULL; + } + + GrPathRenderer* fRenderer; + }; + // Helper for determining if we can treat a thin stroke as a hairline w/ coverage. // If we can, we draw lots faster (raster device does this same test). static bool IsStrokeHairlineOrEquivalent(const SkStrokeRec& stroke, const SkMatrix& matrix, @@ -153,11 +191,14 @@ public: } protected: + const SkPath& path() const { + return fPath; + } + /** * Subclass overrides if it has any limitations of stenciling support. */ - virtual StencilSupport onGetStencilSupport(const SkPath&, - const SkStrokeRec&, + virtual StencilSupport onGetStencilSupport(const SkStrokeRec&, const GrDrawTarget*) const { return kNoRestriction_StencilSupport; } @@ -165,8 +206,7 @@ protected: /** * Subclass implementation of drawPath() */ - virtual bool onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, + virtual bool onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) = 0; @@ -174,7 +214,7 @@ protected: * Subclass implementation of stencilPath(). Subclass must override iff it ever returns * kStencilOnly in onGetStencilSupport(). */ - virtual void onStencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) { + virtual void onStencilPath(const SkStrokeRec& stroke, GrDrawTarget* target) { GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); GrDrawState* drawState = target->drawState(); GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil, @@ -186,7 +226,7 @@ protected: 0xffff); drawState->setStencil(kIncrementStencil); drawState->enableState(GrDrawState::kNoColorWrites_StateBit); - this->drawPath(path, stroke, target, false); + this->drawPath(stroke, target, false); } // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set @@ -206,6 +246,7 @@ protected: } private: + SkPath fPath; typedef SkRefCnt INHERITED; }; diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp index cac0475bbf..89112884d3 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -35,6 +35,7 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path, const SkStrokeRec& stroke, const GrDrawTarget* target, DrawType drawType, + SkPath::FillType fillType, StencilSupport* stencilSupport) { if (!fInit) { this->init(); @@ -56,12 +57,11 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path, minStencilSupport = GrPathRenderer::kNoSupport_StencilSupport; } - for (int i = 0; i < fChain.count(); ++i) { - if (fChain[i]->canDrawPath(path, stroke, target, antiAlias)) { + fChain[i]->setPath(path, fillType); + if (fChain[i]->canDrawPath(stroke, target, antiAlias)) { if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) { - GrPathRenderer::StencilSupport support = fChain[i]->getStencilSupport(path, - stroke, + GrPathRenderer::StencilSupport support = fChain[i]->getStencilSupport(stroke, target); if (support < minStencilSupport) { continue; @@ -71,6 +71,7 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path, } return fChain[i]; } + fChain[i]->resetPath(); } return NULL; } diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index d0936d6b28..61711c07ce 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -11,8 +11,7 @@ #include "GrSWMaskHelper.h" //////////////////////////////////////////////////////////////////////////////// -bool GrSoftwarePathRenderer::canDrawPath(const SkPath&, - const SkStrokeRec&, +bool GrSoftwarePathRenderer::canDrawPath(const SkStrokeRec&, const GrDrawTarget*, bool antiAlias) const { if (!antiAlias || NULL == fContext) { @@ -29,7 +28,6 @@ bool GrSoftwarePathRenderer::canDrawPath(const SkPath&, } GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport( - const SkPath&, const SkStrokeRec&, const GrDrawTarget*) const { return GrPathRenderer::kNoSupport_StencilSupport; @@ -113,8 +111,7 @@ void draw_around_inv_path(GrDrawTarget* target, //////////////////////////////////////////////////////////////////////////////// // return true on success; false on failure -bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrSoftwarePathRenderer::onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { @@ -127,16 +124,16 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path, SkMatrix vm = drawState->getViewMatrix(); SkIRect devPathBounds, devClipBounds; - if (!get_path_and_clip_bounds(target, path, vm, + if (!get_path_and_clip_bounds(target, this->path(), vm, &devPathBounds, &devClipBounds)) { - if (path.isInverseFillType()) { + if (this->path().isInverseFillType()) { draw_around_inv_path(target, devClipBounds, devPathBounds); } return true; } SkAutoTUnref<GrTexture> texture( - GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke, + GrSWMaskHelper::DrawPathMaskToTexture(fContext, this->path(), stroke, devPathBounds, antiAlias, &vm)); if (NULL == texture) { @@ -145,7 +142,7 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path, GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds); - if (path.isInverseFillType()) { + if (this->path().isInverseFillType()) { draw_around_inv_path(target, devClipBounds, devPathBounds); } diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h index f8c5620f49..6e8cec4e13 100644 --- a/src/gpu/GrSoftwarePathRenderer.h +++ b/src/gpu/GrSoftwarePathRenderer.h @@ -24,17 +24,14 @@ public: : fContext(context) { } - virtual bool canDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool canDrawPath(const SkStrokeRec&, const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; protected: - virtual StencilSupport onGetStencilSupport(const SkPath&, - const SkStrokeRec&, + virtual StencilSupport onGetStencilSupport(const SkStrokeRec&, const GrDrawTarget*) const SK_OVERRIDE; - virtual bool onDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool onDrawPath(const SkStrokeRec&, GrDrawTarget*, bool antiAlias) SK_OVERRIDE; diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp index 273c01b861..ff287b7735 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp @@ -34,8 +34,7 @@ GrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() { fGpu->unref(); } -bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrStencilAndCoverPathRenderer::canDrawPath(const SkStrokeRec& stroke, const GrDrawTarget* target, bool antiAlias) const { return !stroke.isHairlineStyle() && @@ -45,22 +44,19 @@ bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, } GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( - const SkPath&, const SkStrokeRec& , const GrDrawTarget*) const { return GrPathRenderer::kStencilOnly_StencilSupport; } -void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, - const SkStrokeRec& stroke, +void GrStencilAndCoverPathRenderer::onStencilPath(const SkStrokeRec& stroke, GrDrawTarget* target) { - SkASSERT(!path.isInverseFillType()); - SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke)); - target->stencilPath(p, path.getFillType()); + SkASSERT(!this->path().isInverseFillType()); + SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(this->path(), stroke)); + target->stencilPath(p, this->path().getFillType()); } -bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, +bool GrStencilAndCoverPathRenderer::onDrawPath(const SkStrokeRec& stroke, GrDrawTarget* target, bool antiAlias) { SkASSERT(!antiAlias); @@ -69,9 +65,9 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, GrDrawState* drawState = target->drawState(); SkASSERT(drawState->getStencil().isDisabled()); - SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(path, stroke)); + SkAutoTUnref<GrPath> p(fGpu->getContext()->createPath(this->path(), stroke)); - if (path.isInverseFillType()) { + if (this->path().isInverseFillType()) { GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass, kZero_StencilOp, kZero_StencilOp, @@ -96,7 +92,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path, *drawState->stencil() = kStencilPass; } - target->drawPath(p, path.getFillType()); + target->drawPath(p, this->path().getFillType()); target->drawState()->stencil()->setDisabled(); return true; diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h index 9ebcec9858..4cd6581503 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.h +++ b/src/gpu/GrStencilAndCoverPathRenderer.h @@ -25,23 +25,19 @@ public: virtual ~GrStencilAndCoverPathRenderer(); - virtual bool canDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool canDrawPath(const SkStrokeRec&, const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; protected: - virtual StencilSupport onGetStencilSupport(const SkPath&, - const SkStrokeRec&, + virtual StencilSupport onGetStencilSupport(const SkStrokeRec&, const GrDrawTarget*) const SK_OVERRIDE; - virtual bool onDrawPath(const SkPath&, - const SkStrokeRec&, + virtual bool onDrawPath(const SkStrokeRec&, GrDrawTarget*, bool antiAlias) SK_OVERRIDE; - virtual void onStencilPath(const SkPath&, - const SkStrokeRec&, + virtual void onStencilPath(const SkStrokeRec&, GrDrawTarget*) SK_OVERRIDE; private: |