diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-10 19:10:17 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-10 19:10:17 +0000 |
commit | 45a15f551b5b3c6c747d8eaf6466b7d3b76a8fae (patch) | |
tree | 49c9fd68caf3a90c7ed5a1ac89f418d6ce7b4afb /src | |
parent | 6f9286202831dd807daf9b1e39271da8f390210e (diff) |
Modifications to GrPatherRenderer(Chain) interfaces to support clip mask manager.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6904069
git-svn-id: http://skia.googlecode.com/svn/trunk@6741 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrAddPathRenderers_default.cpp | 13 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 51 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 19 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.cpp | 19 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.h | 52 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 145 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.cpp | 38 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.h | 69 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.h | 16 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverPathRenderer.cpp | 15 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverPathRenderer.h | 32 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 4 |
16 files changed, 257 insertions, 231 deletions
diff --git a/src/gpu/GrAddPathRenderers_default.cpp b/src/gpu/GrAddPathRenderers_default.cpp index 24f10171e7..9be67688d7 100644 --- a/src/gpu/GrAddPathRenderers_default.cpp +++ b/src/gpu/GrAddPathRenderers_default.cpp @@ -12,17 +12,12 @@ #include "GrAAConvexPathRenderer.h" #include "GrSoftwarePathRenderer.h" -void GrPathRenderer::AddPathRenderers(GrContext* ctx, - GrPathRendererChain::UsageFlags flags, - GrPathRendererChain* chain) { +void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) { if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) { chain->addPathRenderer(pr)->unref(); } - if (!(GrPathRendererChain::kNonAAOnly_UsageFlag & flags)) { - - if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) { - chain->addPathRenderer(pr)->unref(); - } - chain->addPathRenderer(SkNEW(GrAAConvexPathRenderer))->unref(); + if (GrPathRenderer* pr = GrAAHairLinePathRenderer::Create(ctx)) { + chain->addPathRenderer(pr)->unref(); } + chain->addPathRenderer(SkNEW(GrAAConvexPathRenderer))->unref(); } diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index c4004861ca..11b301d61a 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -70,7 +70,11 @@ bool path_needs_SW_renderer(GrContext* context, path.writable()->toggleInverseFillType(); } // last (false) parameter disallows use of the SW path renderer - return NULL == context->getPathRenderer(*path, stroke, gpu, doAA, false); + GrPathRendererChain::DrawType type = doAA ? + GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; + + return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); } } @@ -313,10 +317,14 @@ bool GrClipMaskManager::drawClipShape(GrTexture* target, const SkClipStack::Elem } SkStroke stroke; stroke.setDoFill(true); + GrPathRendererChain::DrawType type = element->isAA() ? + GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; GrPathRenderer* pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, - element->isAA(), false); + false, + type); if (NULL == pr) { return false; } @@ -580,10 +588,9 @@ bool GrClipMaskManager::createStencilClipMask(InitialState initialState, drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); } - // Can the clip element be drawn directly to the stencil buffer - // with a non-inverted fill rule without extra passes to - // resolve in/out status? - bool canRenderDirectToStencil = false; + // This will be used to determine whether the clip shape can be rendered into the + // stencil with arbitrary stencil settings. + GrPathRenderer::StencilSupport stencilSupport; SkStroke stroke; stroke.setDoFill(true); @@ -591,29 +598,37 @@ bool GrClipMaskManager::createStencilClipMask(InitialState initialState, SkRegion::Op op = element->getOp(); GrPathRenderer* pr = NULL; - SkPath clipPath; + SkTCopyOnFirstWrite<SkPath> clipPath; if (Element::kRect_Type == element->getType()) { - canRenderDirectToStencil = true; + stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; fill = SkPath::kEvenOdd_FillType; fillInverted = false; } else { GrAssert(Element::kPath_Type == element->getType()); - clipPath = element->getPath(); - fill = clipPath.getFillType(); - fillInverted = clipPath.isInverseFillType(); - fill = SkPath::NonInverseFill(fill); - clipPath.setFillType(fill); - pr = this->getContext()->getPathRenderer(clipPath, stroke, fGpu, false, true); + clipPath.init(element->getPath()); + fill = clipPath->getFillType(); + fillInverted = clipPath->isInverseFillType(); + if (fillInverted) { + clipPath.writable()->toggleInverseFillType(); + fill = clipPath->getFillType(); + } + pr = this->getContext()->getPathRenderer(*clipPath, + stroke, + fGpu, + false, + GrPathRendererChain::kStencilOnly_DrawType, + &stencilSupport); if (NULL == pr) { fGpu->setClip(oldClipData); return false; } - canRenderDirectToStencil = !pr->requiresStencilPass(clipPath, stroke, fGpu); } int passes; GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; + bool canRenderDirectToStencil = + GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; bool canDrawDirectToClip; // Given the renderer, the element, // fill rule, and set operation can // we render the element directly to @@ -642,9 +657,9 @@ bool GrClipMaskManager::createStencilClipMask(InitialState initialState, GrAssert(Element::kPath_Type == element->getType()); if (canRenderDirectToStencil) { *drawState->stencil() = gDrawToStencil; - pr->drawPath(clipPath, stroke, fGpu, false); + pr->drawPath(*clipPath, stroke, fGpu, false); } else { - pr->drawPathToStencil(clipPath, stroke, fGpu); + pr->stencilPath(*clipPath, stroke, fGpu); } } } @@ -661,7 +676,7 @@ bool GrClipMaskManager::createStencilClipMask(InitialState initialState, } else { GrAssert(Element::kPath_Type == element->getType()); SET_RANDOM_COLOR - pr->drawPath(clipPath, stroke, fGpu, false); + pr->drawPath(*clipPath, stroke, fGpu, false); } } else { SET_RANDOM_COLOR diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index d96a16e9aa..c39ee75519 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1112,7 +1112,10 @@ void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const prAA = false; } - GrPathRenderer* pr = this->getPathRenderer(path, stroke, target, prAA, true); + GrPathRendererChain::DrawType type = prAA ? GrPathRendererChain::kColorAntiAlias_DrawType : + GrPathRendererChain::kColor_DrawType; + + GrPathRenderer* pr = this->getPathRenderer(path, stroke, target, true, type); if (NULL == pr) { #if GR_DEBUG GrPrintf("Unable to find path renderer compatible with path.\n"); @@ -1620,24 +1623,24 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffer GrPathRenderer* GrContext::getPathRenderer(const SkPath& path, const SkStroke& stroke, const GrDrawTarget* target, - bool antiAlias, - bool allowSW) { + bool allowSW, + GrPathRendererChain::DrawType drawType, + GrPathRendererChain::StencilSupport* stencilSupport) { + if (NULL == fPathRendererChain) { - fPathRendererChain = - SkNEW_ARGS(GrPathRendererChain, - (this, GrPathRendererChain::kNone_UsageFlag)); + fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); } GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, stroke, target, - antiAlias); + drawType, + stencilSupport); if (NULL == pr && allowSW) { if (NULL == fSoftwarePathRenderer) { fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); } - pr = fSoftwarePathRenderer; } diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index f80b4d793f..b92b77d095 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -162,10 +162,15 @@ static inline bool single_pass_path(const SkPath& path, const SkStroke& stroke) #endif } -bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target) const { - return !single_pass_path(path, stroke); +GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport( + const SkPath& path, + const SkStroke& stroke, + const GrDrawTarget*) const { + if (single_pass_path(path, stroke)) { + return GrPathRenderer::kNoRestriction_StencilSupport; + } else { + return GrPathRenderer::kStencilOnly_StencilSupport; + } } static inline void append_countour_edge_indices(bool hairLine, @@ -508,9 +513,9 @@ bool GrDefaultPathRenderer::onDrawPath(const SkPath& path, false); } -void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target) { +void GrDefaultPathRenderer::onStencilPath(const SkPath& path, + const SkStroke& stroke, + GrDrawTarget* target) { GrAssert(SkPath::kInverseEvenOdd_FillType != path.getFillType()); GrAssert(SkPath::kInverseWinding_FillType != path.getFillType()); this->internalDrawPath(path, stroke, target, true); diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h index e98f2d77fc..657537a6ef 100644 --- a/src/gpu/GrDefaultPathRenderer.h +++ b/src/gpu/GrDefaultPathRenderer.h @@ -12,48 +12,46 @@ #include "SkTemplates.h" /** - * Subclass that renders the path using the stencil buffer to resolve fill - * rules (e.g. winding, even-odd) + * Subclass that renders the path using the stencil buffer to resolve fill rules + * (e.g. winding, even-odd) */ class GR_API GrDefaultPathRenderer : public GrPathRenderer { public: - GrDefaultPathRenderer(bool separateStencilSupport, - bool stencilWrapOpsSupport); + GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport); - - virtual bool requiresStencilPass(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target) const SK_OVERRIDE; - - virtual bool canDrawPath(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target, + virtual bool canDrawPath(const SkPath&, + const SkStroke&, + const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; - virtual void drawPathToStencil(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target) SK_OVERRIDE; - private: - virtual bool onDrawPath(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target, + virtual StencilSupport onGetStencilSupport(const SkPath&, + const SkStroke&, + const GrDrawTarget*) const SK_OVERRIDE; + + virtual bool onDrawPath(const SkPath&, + const SkStroke&, + GrDrawTarget*, bool antiAlias) SK_OVERRIDE; - bool internalDrawPath(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target, + virtual void onStencilPath(const SkPath&, + const SkStroke&, + GrDrawTarget*) SK_OVERRIDE; + + bool internalDrawPath(const SkPath&, + const SkStroke&, + GrDrawTarget*, bool stencilOnly); - bool createGeom(const SkPath& path, - const SkStroke& stroke, + bool createGeom(const SkPath&, + const SkStroke&, SkScalar srcSpaceTol, - GrDrawTarget* target, - GrPrimitiveType* primType, + GrDrawTarget*, + GrPrimitiveType*, int* vertexCnt, int* indexCnt, - GrDrawTarget::AutoReleaseGeometry* arg); + GrDrawTarget::AutoReleaseGeometry*); bool fSeparateStencil; bool fStencilWrapOps; diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index afcd3c9c22..9d525663f1 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -12,72 +12,86 @@ #include "GrDrawTarget.h" #include "GrPathRendererChain.h" +#include "GrStencil.h" +#include "SkStroke.h" #include "SkTArray.h" class SkPath; -class SkStroke; struct GrPoint; /** * Base class for drawing paths into a GrDrawTarget. * - * Derived classes can use stages GrPaint::kTotalStages through - * GrDrawState::kNumStages-1. The stages before GrPaint::kTotalStages - * are reserved for setting up the draw (i.e., textures and filter masks). + * Derived classes can use stages GrPaint::kTotalStages through GrDrawState::kNumStages-1. The + * stages before GrPaint::kTotalStages are reserved for setting up the draw (i.e., textures and + * filter masks). */ class GR_API GrPathRenderer : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrPathRenderer) /** - * This is called to install custom path renderers in every GrContext at - * create time. The default implementation in GrCreatePathRenderer_none.cpp - * does not add any additional renderers. Link against another - * implementation to install your own. The first added is the most preferred - * path renderer, second is second most preferred, etc. + * This is called to install custom path renderers in every GrContext at create time. The + * default implementation in GrCreatePathRenderer_none.cpp does not add any additional + * renderers. Link against another implementation to install your own. The first added is the + * most preferred path renderer, second is second most preferred, etc. * * @param context the context that will use the path renderer - * @param flags flags indicating how path renderers will be used * @param prChain the chain to add path renderers to. */ - static void AddPathRenderers(GrContext* context, - GrPathRendererChain::UsageFlags flags, - GrPathRendererChain* prChain); + static void AddPathRenderers(GrContext* context, GrPathRendererChain* prChain); GrPathRenderer(); /** - * For complex clips Gr uses the stencil buffer. The path renderer must be - * able to render paths into the stencil buffer. However, the path renderer - * itself may require the stencil buffer to resolve the path fill rule. - * This function queries whether the path render needs its own stencil - * pass. If this returns false then drawPath() should not modify the - * the target's stencil settings but use those already set on target. The - * target is passed as a param in case the answer depends upon draw state. + * A caller may wish to use a path renderer to draw a path into the stencil buffer. However, + * the path renderer itself may require use of the stencil buffer. Also a path renderer may + * use a GrEffect coverage stage that sets coverage to zero to eliminate pixels that are covered + * by bounding geometry but outside the path. These exterior pixels would still be rendered into + * the stencil. + * + * A GrPathRenderer can provide three levels of support for stenciling paths: + * 1) kNoRestriction: This is the most general. The caller sets up the GrDrawState on the target + * and calls drawPath(). The path is rendered exactly as the draw state + * indicates including support for simultaneous color and stenciling with + * arbitrary stenciling rules. Pixels partially covered by AA paths are + * affected by the stencil settings. + * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil + * simultaneously. The path renderer does support the stencilPath() function + * which performs no color writes and writes a non-zero stencil value to pixels + * covered by the path. + * 3) kNoSupport: This path renderer cannot be used to stencil the path. + */ + typedef GrPathRendererChain::StencilSupport StencilSupport; + static const StencilSupport kNoSupport_StencilSupport = + GrPathRendererChain::kNoSupport_StencilSupport; + static const StencilSupport kStencilOnly_StencilSupport = + GrPathRendererChain::kStencilOnly_StencilSupport; + static const StencilSupport kNoRestriction_StencilSupport = + GrPathRendererChain::kNoRestriction_StencilSupport; + + /** + * This function is to get the stencil support for a particular 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). - * - * @return false if this path renderer can generate interior-only fragments - * without changing the stencil settings on the target. If it - * returns true the drawPathToStencil will be used when rendering - * clips. */ - virtual bool requiresStencilPass(const SkPath& path, + StencilSupport getStencilSupport(const SkPath& path, const SkStroke& stroke, const GrDrawTarget* target) const { - return false; + GrAssert(!path.isInverseFillType()); + return this->onGetStencilSupport(path, stroke, target); } /** - * 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 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) @@ -91,55 +105,72 @@ public: const GrDrawTarget* target, bool antiAlias) const = 0; /** - * Draws the path into the draw target. If requiresStencilBuffer returned - * false then the target may be setup for stencil rendering (since the - * path renderer didn't claim that it needs to use the stencil internally). + * 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. * * @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. */ - virtual bool drawPath(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target, - bool antiAlias) { + bool drawPath(const SkPath& path, + const SkStroke& stroke, + GrDrawTarget* target, + bool antiAlias) { GrAssert(this->canDrawPath(path, stroke, target, antiAlias)); return this->onDrawPath(path, stroke, target, antiAlias); } /** - * Draws the path to the stencil buffer. Assume the writable stencil bits - * are already initialized to zero. Fill will always be either - * kWinding_FillType or kEvenOdd_FillType. - * - * Only called if requiresStencilPass returns true for the same combo of - * target, path, and fill. Never called with an inverse fill. - * - * The default implementation assumes the path filling algorithm doesn't - * require a separate stencil pass and so crashes. + * 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. * + * @param path the path to draw. + * @param stroke the stroke information (width, join, cap) + * @param target target that the path will be rendered to */ - virtual void drawPathToStencil(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target) { - GrCrash("Unexpected call to drawPathToStencil."); + void stencilPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target) { + GrAssert(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target)); + this->onStencilPath(path, stroke, target); } protected: /** - * Draws the path into the draw target. - * - * @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 whether antialiasing is enabled or not. + * Subclass overrides if it has any limitations of stenciling support. + */ + virtual StencilSupport onGetStencilSupport(const SkPath&, + const SkStroke&, + const GrDrawTarget*) const { + return kNoRestriction_StencilSupport; + } + + /** + * Subclass implementation of drawPath() */ virtual bool onDrawPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target, bool antiAlias) = 0; + /** + * Subclass implementation of stencilPath(). Subclass must override iff it ever returns + * kStencilOnly in onGetStencilSupport(). + */ + virtual void onStencilPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target) { + GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); + GrDrawState* drawState = target->drawState(); + GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil, + kReplace_StencilOp, + kReplace_StencilOp, + kAlways_StencilFunc, + 0xffff, + 0xffff, + 0xffff); + drawState->setStencil(kIncrementStencil); + drawState->enableState(GrDrawState::kNoColorWrites_StateBit); + this->drawPath(path, stroke, target, false); + } + private: typedef GrRefCnt INHERITED; diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp index 8ccafcfe37..6cb45fa10f 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -15,10 +15,9 @@ SK_DEFINE_INST_COUNT(GrPathRendererChain) -GrPathRendererChain::GrPathRendererChain(GrContext* context, UsageFlags flags) +GrPathRendererChain::GrPathRendererChain(GrContext* context) : fInit(false) - , fOwner(context) - , fFlags(flags) { + , fOwner(context) { } GrPathRendererChain::~GrPathRendererChain() { @@ -36,12 +35,41 @@ GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) { GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path, const SkStroke& stroke, const GrDrawTarget* target, - bool antiAlias) { + DrawType drawType, + StencilSupport* stencilSupport) { if (!fInit) { this->init(); } + bool antiAlias = (kColorAntiAlias_DrawType == drawType || + kStencilAndColorAntiAlias_DrawType == drawType); + + GR_STATIC_ASSERT(GrPathRenderer::kNoSupport_StencilSupport < + GrPathRenderer::kStencilOnly_StencilSupport); + GR_STATIC_ASSERT(GrPathRenderer::kStencilOnly_StencilSupport < + GrPathRenderer::kNoRestriction_StencilSupport); + GrPathRenderer::StencilSupport minStencilSupport; + if (kStencilOnly_DrawType == drawType) { + minStencilSupport = GrPathRenderer::kStencilOnly_StencilSupport; + } else if (kStencilAndColor_DrawType == drawType || + kStencilAndColorAntiAlias_DrawType == drawType) { + minStencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; + } else { + minStencilSupport = GrPathRenderer::kNoSupport_StencilSupport; + } + + for (int i = 0; i < fChain.count(); ++i) { if (fChain[i]->canDrawPath(path, stroke, target, antiAlias)) { + if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) { + GrPathRenderer::StencilSupport support = fChain[i]->getStencilSupport(path, + stroke, + target); + if (support < minStencilSupport) { + continue; + } else if (NULL != stencilSupport) { + *stencilSupport = support; + } + } return fChain[i]; } } @@ -53,7 +81,7 @@ void GrPathRendererChain::init() { GrGpu* gpu = fOwner->getGpu(); bool twoSided = gpu->getCaps().twoSidedStencilSupport(); bool wrapOp = gpu->getCaps().stencilWrapOpsSupport(); - GrPathRenderer::AddPathRenderers(fOwner, fFlags, this); + GrPathRenderer::AddPathRenderers(fOwner, this); this->addPathRenderer(SkNEW_ARGS(GrDefaultPathRenderer, (twoSided, wrapOp)))->unref(); fInit = true; diff --git a/src/gpu/GrPathRendererChain.h b/src/gpu/GrPathRendererChain.h deleted file mode 100644 index dfc696deb5..0000000000 --- a/src/gpu/GrPathRendererChain.h +++ /dev/null @@ -1,69 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#ifndef GrPathRendererChain_DEFINED -#define GrPathRendererChain_DEFINED - -#include "GrDrawTarget.h" -#include "GrRefCnt.h" -#include "SkTArray.h" - -class GrContext; - -class SkPath; -class SkStroke; -class GrPathRenderer; - -/** - * Keeps track of an ordered list of path renderers. When a path needs to be - * drawn this list is scanned to find the most preferred renderer. To add your - * path renderer to the list implement the GrPathRenderer::AddPathRenderers - * function. - */ -class GrPathRendererChain : public SkRefCnt { -public: - SK_DECLARE_INST_COUNT(GrPathRendererChain) - - enum UsageFlags { - kNone_UsageFlag = 0, - kNonAAOnly_UsageFlag = 1, - }; - - GrPathRendererChain(GrContext* context, UsageFlags flags); - - ~GrPathRendererChain(); - - // takes a ref and unrefs in destructor - GrPathRenderer* addPathRenderer(GrPathRenderer* pr); - - GrPathRenderer* getPathRenderer(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target, - bool antiAlias); - -private: - - GrPathRendererChain(); - - void init(); - - enum { - kPreAllocCount = 8, - }; - bool fInit; - GrContext* fOwner; - UsageFlags fFlags; - SkSTArray<kPreAllocCount, GrPathRenderer*, true> fChain; - - typedef SkRefCnt INHERITED; -}; - -GR_MAKE_BITFIELD_OPS(GrPathRendererChain::UsageFlags) - -#endif diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index 528785846f..da42e8cff8 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -325,7 +325,7 @@ void reduced_stack_walker(const SkClipStack& stack, ++numAAElements; } // Intersecting an inverse shape is the same as differencing the non-inverse shape. - // Replacing with a inverse shape the same as setting initialState=kAllIn and + // Replacing with an inverse shape is the same as setting initialState=kAllIn and // differencing the non-inverse shape. bool isReplace = SkRegion::kReplace_Op == newElement->getOp(); if (newElement->isInverseFilled() && diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index a521eefcac..36a4156369 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -28,6 +28,13 @@ bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path, return true; } +GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport( + const SkPath&, + const SkStroke&, + const GrDrawTarget*) const { + return GrPathRenderer::kNoSupport_StencilSupport; +} + namespace { //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h index 7c7382cbd6..dd78d6b406 100644 --- a/src/gpu/GrSoftwarePathRenderer.h +++ b/src/gpu/GrSoftwarePathRenderer.h @@ -24,14 +24,18 @@ public: : fContext(context) { } - virtual bool canDrawPath(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target, + virtual bool canDrawPath(const SkPath&, + const SkStroke&, + const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; protected: - virtual bool onDrawPath(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target, + virtual StencilSupport onGetStencilSupport(const SkPath&, + const SkStroke&, + const GrDrawTarget*) const SK_OVERRIDE; + + virtual bool onDrawPath(const SkPath&, + const SkStroke&, + GrDrawTarget*, bool antiAlias) SK_OVERRIDE; private: diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp index 28e18edf8d..a9bddda2b2 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp @@ -42,15 +42,16 @@ bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path, target->getDrawState().getStencil().isDisabled(); } -bool GrStencilAndCoverPathRenderer::requiresStencilPass(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target) const { - return true; +GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport( + const SkPath&, + const SkStroke& , + const GrDrawTarget*) const { + return GrPathRenderer::kStencilOnly_StencilSupport; } -void GrStencilAndCoverPathRenderer::drawPathToStencil(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target) { +void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path, + const SkStroke& stroke, + GrDrawTarget* target) { GrAssert(!path.isInverseFillType()); SkAutoTUnref<GrPath> p(fGpu->createPath(path)); target->stencilPath(p, stroke, path.getFillType()); diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h index 9a8dd57b20..3b830e3e83 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.h +++ b/src/gpu/GrStencilAndCoverPathRenderer.h @@ -21,31 +21,31 @@ class GrGpu; class GrStencilAndCoverPathRenderer : public GrPathRenderer { public: - static GrPathRenderer* Create(GrContext* context); + static GrPathRenderer* Create(GrContext*); virtual ~GrStencilAndCoverPathRenderer(); - virtual bool canDrawPath(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target, + virtual bool canDrawPath(const SkPath&, + const SkStroke&, + const GrDrawTarget*, bool antiAlias) const SK_OVERRIDE; - virtual bool requiresStencilPass(const SkPath& path, - const SkStroke& stroke, - const GrDrawTarget* target) const SK_OVERRIDE; - - virtual void drawPathToStencil(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target) SK_OVERRIDE; - protected: - virtual bool onDrawPath(const SkPath& path, - const SkStroke& stroke, - GrDrawTarget* target, + virtual StencilSupport onGetStencilSupport(const SkPath&, + const SkStroke&, + const GrDrawTarget*) const SK_OVERRIDE; + + virtual bool onDrawPath(const SkPath&, + const SkStroke&, + GrDrawTarget*, bool antiAlias) SK_OVERRIDE; + virtual void onStencilPath(const SkPath&, + const SkStroke&, + GrDrawTarget*) SK_OVERRIDE; + private: - GrStencilAndCoverPathRenderer(GrGpu* gpu); + GrStencilAndCoverPathRenderer(GrGpu*); GrGpu* fGpu; diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 0283a5ae13..ba86383201 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -284,6 +284,9 @@ bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, GrCrash("Unknown Edge Type!"); break; } + if (fDesc.fDiscardIfOutsideEdge) { + builder->fFSCode.appendf("\tif (edgeAlpha <= 0) {\n\t\tdiscard;\n\t}\n"); + } *coverageVar = "edgeAlpha"; return true; } else { diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index d385e6070e..3902a8c028 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -108,7 +108,10 @@ public: kDualSrcOutputCnt }; + // TODO: remove these two members when edge-aa can be rewritten as a GrEffect. GrDrawState::VertexEdgeType fVertexEdgeType; + // should the FS discard if the edge-aa coverage is zero (to avoid stencil manipulation) + bool fDiscardIfOutsideEdge; // stripped of bits that don't affect program generation GrVertexLayout fVertexLayout; diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 73f60ca989..5850fc4d69 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -553,9 +553,11 @@ void GrGpuGL::buildProgram(bool isPoints, if (!skipCoverage && (desc->fVertexLayout &GrDrawTarget::kEdge_VertexLayoutBit)) { desc->fVertexEdgeType = drawState.getVertexEdgeType(); + desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); } else { - // use canonical value when not set to avoid cache misses + // Use canonical values when edge-aa is not enabled to avoid program cache misses. desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; + desc->fDiscardIfOutsideEdge = false; } for (int s = 0; s < GrDrawState::kNumStages; ++s) { |