aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2015-10-26 08:33:10 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-26 08:33:10 -0700
commit5c3ea4cd3921e8904d4f201bcdedfd5b8a726542 (patch)
tree6dd7ca7a1cf6ff120496d6fe6b26f6c8db0a7682 /src
parent950305ec77702639fe6ad1923f7b8d828ccef634 (diff)
Fix ClipMaskManager's SW-fallback logic
'useSWOnlyPath' was not correctly toggling between stencil and color draws so there was a mismatch with the behavior in createAlphaClipMask (i.e., we were inadvertently rendering some of the elements in a clip using SW but using stenciling for others - precisely what 'useSWOnlyPath' was intended to prevent). Review URL: https://codereview.chromium.org/1421533007
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClipMaskManager.cpp133
-rw-r--r--src/gpu/GrClipMaskManager.h8
-rw-r--r--src/gpu/GrContext.cpp2
-rw-r--r--src/gpu/GrDrawContext.cpp6
-rw-r--r--src/gpu/GrPathRendererChain.cpp16
5 files changed, 89 insertions, 76 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index b57f3cc1bc..b87788b286 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -46,24 +46,71 @@ static const GrFragmentProcessor* create_fp_for_mask(GrTexture* result, const Sk
kDevice_GrCoordSet);
}
+// Does the path in 'element' require SW rendering? If so, return true (and,
+// optionally, set 'prOut' to NULL. If not, return false (and, optionally, set
+// 'prOut' to the non-SW path renderer that will do the job).
static bool path_needs_SW_renderer(GrContext* context,
const GrPipelineBuilder& pipelineBuilder,
const SkMatrix& viewMatrix,
- const SkPath& origPath,
- const GrStrokeInfo& 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();
+ const Element* element,
+ GrPathRenderer** prOut,
+ bool needsStencil) {
+ if (Element::kRect_Type == element->getType()) {
+ // rects can always be drawn directly w/o using the software path
+ // TODO: skip rrects once we're drawing them directly.
+ return false;
+ } else {
+ // We shouldn't get here with an empty clip element.
+ SkASSERT(Element::kEmpty_Type != element->getType());
+
+ // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
+ SkPath path;
+ element->asPath(&path);
+ if (path.isInverseFillType()) {
+ path.toggleInverseFillType();
+ }
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
+
+ GrPathRendererChain::DrawType type;
+
+ if (needsStencil) {
+ type = element->isAA()
+ ? GrPathRendererChain::kStencilAndColorAntiAlias_DrawType
+ : GrPathRendererChain::kStencilAndColor_DrawType;
+ } else {
+ type = element->isAA()
+ ? GrPathRendererChain::kColorAntiAlias_DrawType
+ : GrPathRendererChain::kColor_DrawType;
+ }
+
+ // the 'false' parameter disallows use of the SW path renderer
+ GrPathRenderer* pr = context->getPathRenderer(pipelineBuilder, viewMatrix, path,
+ stroke, false, type);
+ if (prOut) {
+ *prOut = pr;
+ }
+ return SkToBool(!pr);
}
- // last (false) parameter disallows use of the SW path renderer
- GrPathRendererChain::DrawType type = doAA ?
- GrPathRendererChain::kColorAntiAlias_DrawType :
- GrPathRendererChain::kColor_DrawType;
+}
- return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *path, stroke,
- false, type);
+// 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.
+static bool can_stencil_and_draw_element(GrContext* context,
+ GrPipelineBuilder* pipelineBuilder,
+ GrTexture* texture,
+ const SkMatrix& viewMatrix,
+ const SkClipStack::Element* element,
+ GrPathRenderer** pr) {
+ pipelineBuilder->setRenderTarget(texture->asRenderTarget());
+
+ static const bool kNeedsStencil = true;
+ return !path_needs_SW_renderer(context,
+ *pipelineBuilder,
+ viewMatrix,
+ element,
+ pr,
+ kNeedsStencil);
}
GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
@@ -84,24 +131,22 @@ bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
// TODO: generalize this function so that when
// a clip gets complex enough it can just be done in SW regardless
// of whether it would invoke the GrSoftwarePathRenderer.
- GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
- SkMatrix translate;
- translate.setTranslate(clipToMaskOffset);
+ const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
const Element* element = iter.get();
- // rects can always be drawn directly w/o using the software path
- // Skip rrects once we're drawing them directly.
- if (Element::kRect_Type != element->getType()) {
- SkPath path;
- element->asPath(&path);
- if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate,
- path, stroke, element->isAA())) {
- return true;
- }
+
+ SkRegion::Op op = element->getOp();
+ bool invert = element->isInverseFilled();
+ bool needsStencil = invert ||
+ SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op;
+
+ if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate,
+ element, nullptr, needsStencil)) {
+ return true;
}
}
return false;
@@ -412,7 +457,7 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
GrPathRendererChain::DrawType type;
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
GrPathRendererChain::kColor_DrawType;
- pr = this->getContext()->getPathRenderer(pipelineBuilder, viewMatrix,
+ pr = this->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
path, stroke, false, type);
}
if (nullptr == pr) {
@@ -434,32 +479,6 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
return true;
}
-bool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuilder,
- GrTexture* target,
- GrPathRenderer** pr,
- const SkClipStack::Element* element) {
- pipelineBuilder->setRenderTarget(target->asRenderTarget());
-
- if (Element::kRect_Type == element->getType()) {
- return true;
- } else {
- // We shouldn't get here with an empty clip element.
- SkASSERT(Element::kEmpty_Type != element->getType());
- SkPath path;
- element->asPath(&path);
- if (path.isInverseFillType()) {
- path.toggleInverseFillType();
- }
- GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
- GrPathRendererChain::DrawType type = element->isAA() ?
- GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
- GrPathRendererChain::kStencilAndColor_DrawType;
- *pr = this->getContext()->getPathRenderer(pipelineBuilder, SkMatrix::I(), path,
- stroke, false, type);
- return SkToBool(*pr);
- }
-}
-
void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder,
GrTexture* dstMask,
GrTexture* srcMask,
@@ -555,8 +574,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
- SkMatrix translate;
- translate.setTranslate(clipToMaskOffset);
+ const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
@@ -586,7 +604,8 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
pipelineBuilder.setClip(clip);
GrPathRenderer* pr = nullptr;
- bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, texture, &pr, element);
+ bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pipelineBuilder,
+ texture, translate, element, &pr);
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
@@ -594,6 +613,8 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
// the accumulator.
SkIRect maskSpaceElementIBounds;
+ SkASSERT(!useTemp);
+
if (useTemp) {
if (invert) {
maskSpaceElementIBounds = maskSpaceIBounds;
@@ -759,7 +780,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
if (fillInverted) {
clipPath.toggleInverseFillType();
}
- pr = this->getContext()->getPathRenderer(&pipelineBuilder,
+ pr = this->getContext()->getPathRenderer(pipelineBuilder,
viewMatrix,
clipPath,
stroke,
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 3ce3e72bf1..515f4b6583 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -133,14 +133,6 @@ private:
const SkClipStack::Element*,
GrPathRenderer* pr = nullptr);
- // 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(GrPipelineBuilder*,
- GrTexture* target,
- GrPathRenderer**,
- const SkClipStack::Element*);
-
void mergeMask(GrPipelineBuilder*,
GrTexture* dstMask,
GrTexture* srcMask,
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 081bc0ac38..04e1b8d203 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -541,7 +541,7 @@ void GrContext::flushSurfaceWrites(GrSurface* surface) {
* Due to its expense, the software path renderer has split out so it can
* can be individually allowed/disallowed via the "allowSW" boolean.
*/
-GrPathRenderer* GrContext::getPathRenderer(const GrPipelineBuilder* pipelineBuilder,
+GrPathRenderer* GrContext::getPathRenderer(const GrPipelineBuilder& pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
const GrStrokeInfo& stroke,
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index f52d7dcd15..d64273a828 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -691,7 +691,7 @@ void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
// Try a 1st time without stroking the path and without allowing the SW renderer
- GrPathRenderer* pr = fDrawingManager->getContext()->getPathRenderer(pipelineBuilder,
+ GrPathRenderer* pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder,
viewMatrix, *pathPtr,
*strokeInfoPtr, false,
type);
@@ -707,7 +707,7 @@ void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
return;
}
strokeInfoPtr = &dashlessStrokeInfo;
- pr = fDrawingManager->getContext()->getPathRenderer(pipelineBuilder, viewMatrix,
+ pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
*pathPtr, *strokeInfoPtr,
false, type);
}
@@ -732,7 +732,7 @@ void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
}
// This time, allow SW renderer
- pr = fDrawingManager->getContext()->getPathRenderer(pipelineBuilder, viewMatrix,
+ pr = fDrawingManager->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix,
*pathPtr, *strokeInfoPtr,
true, type);
}
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index b1eb3202bf..c846dee5b3 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -40,7 +40,7 @@ GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) {
}
GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrShaderCaps* shaderCaps,
- const GrPipelineBuilder* pipelineBuilder,
+ const GrPipelineBuilder& pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
const GrStrokeInfo& stroke,
@@ -66,15 +66,15 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrShaderCaps* shaderC
minStencilSupport = GrPathRenderer::kNoSupport_StencilSupport;
}
+ GrPathRenderer::CanDrawPathArgs args;
+ args.fShaderCaps = shaderCaps;
+ args.fPipelineBuilder = &pipelineBuilder;
+ args.fViewMatrix = &viewMatrix;
+ args.fPath = &path;
+ args.fStroke = &stroke;
+ args.fAntiAlias = antiAlias;
for (int i = 0; i < fChain.count(); ++i) {
- GrPathRenderer::CanDrawPathArgs args;
- args.fShaderCaps = shaderCaps;
- args.fPipelineBuilder = pipelineBuilder;
- args.fViewMatrix = &viewMatrix;
- args.fPath = &path;
- args.fStroke = &stroke;
- args.fAntiAlias = antiAlias;
if (fChain[i]->canDrawPath(args)) {
if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) {
GrPathRenderer::StencilSupport support =