aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-10 19:10:17 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-10 19:10:17 +0000
commit45a15f551b5b3c6c747d8eaf6466b7d3b76a8fae (patch)
tree49c9fd68caf3a90c7ed5a1ac89f418d6ce7b4afb /src
parent6f9286202831dd807daf9b1e39271da8f390210e (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.cpp13
-rw-r--r--src/gpu/GrClipMaskManager.cpp51
-rw-r--r--src/gpu/GrContext.cpp19
-rw-r--r--src/gpu/GrDefaultPathRenderer.cpp19
-rw-r--r--src/gpu/GrDefaultPathRenderer.h52
-rw-r--r--src/gpu/GrPathRenderer.h145
-rw-r--r--src/gpu/GrPathRendererChain.cpp38
-rw-r--r--src/gpu/GrPathRendererChain.h69
-rw-r--r--src/gpu/GrReducedClip.cpp2
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp7
-rw-r--r--src/gpu/GrSoftwarePathRenderer.h16
-rw-r--r--src/gpu/GrStencilAndCoverPathRenderer.cpp15
-rw-r--r--src/gpu/GrStencilAndCoverPathRenderer.h32
-rw-r--r--src/gpu/gl/GrGLProgram.cpp3
-rw-r--r--src/gpu/gl/GrGLProgram.h3
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp4
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) {