aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-07 19:43:43 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-07 19:43:43 +0000
commite5a041c0688ccb861cc85f8917338602864d8e5a (patch)
treea6d19f9f4643284ec9ef9808e4a3a6736f12c4e4
parent8c2ee5963505cdbe128f68d67f064a3901d22a3c (diff)
Implement the clip as 4 or fewer GrEffects when possible.
BUG=skia:2181 R=robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/188693008 git-svn-id: http://skia.googlecode.com/svn/trunk@13710 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--expectations/gm/ignored-tests.txt6
-rw-r--r--src/gpu/GrClipMaskManager.cpp168
-rw-r--r--src/gpu/GrClipMaskManager.h7
-rw-r--r--src/gpu/effects/GrConvexPolyEffect.cpp4
-rw-r--r--src/gpu/effects/GrRRectEffect.cpp6
5 files changed, 136 insertions, 55 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index dec7f8d718..e09a5ec188 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -42,3 +42,9 @@ inverse_paths
bezier_quad_effects
bezier_conic_effects
bezier_cubic_effects
+
+# bsalomon: These tests change slightly due to https://codereview.chromium.org/188693008/
+gpu/complexclip2_rrect_aa
+gpu/complexclip2_rect_aa
+convex_poly_effect
+rrect_effect
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index e24c759688..96f4b209e3 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -107,6 +107,106 @@ bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
return false;
}
+bool GrClipMaskManager::installClipEffects(const ElementList& elements,
+ GrDrawState::AutoRestoreEffects* are,
+ const SkVector& clipToRTOffset,
+ const SkRect* drawBounds) {
+
+ GrDrawState* drawState = fGpu->drawState();
+ SkRect boundsInClipSpace;
+ if (NULL != drawBounds) {
+ boundsInClipSpace = *drawBounds;
+ boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
+ }
+
+ are->set(drawState);
+ GrRenderTarget* rt = drawState->getRenderTarget();
+ ElementList::Iter iter(elements);
+
+ bool setARE = false;
+ bool failed = false;
+
+ while (NULL != iter.get()) {
+ SkRegion::Op op = iter.get()->getOp();
+ bool invert;
+ bool skip = false;
+ switch (op) {
+ case SkRegion::kReplace_Op:
+ SkASSERT(iter.get() == elements.head());
+ // Fallthrough, handled same as intersect.
+ case SkRegion::kIntersect_Op:
+ invert = false;
+ if (NULL != drawBounds && iter.get()->contains(boundsInClipSpace)) {
+ skip = true;
+ }
+ break;
+ case SkRegion::kDifference_Op:
+ invert = true;
+ // We don't currently have a cheap test for whether a rect is fully outside an
+ // element's primitive, so don't attempt to set skip.
+ break;
+ default:
+ failed = true;
+ break;
+ }
+ if (failed) {
+ break;
+ }
+
+ if (!skip) {
+ GrEffectEdgeType edgeType;
+ if (GR_AA_CLIP && iter.get()->isAA()) {
+ if (rt->isMultisampled()) {
+ // Coverage based AA clips don't place nicely with MSAA.
+ failed = true;
+ break;
+ }
+ edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_GrEffectEdgeType;
+ } else {
+ edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_GrEffectEdgeType;
+ }
+ SkAutoTUnref<GrEffectRef> effect;
+ switch (iter.get()->getType()) {
+ case SkClipStack::Element::kPath_Type:
+ effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
+ &clipToRTOffset));
+ break;
+ case SkClipStack::Element::kRRect_Type: {
+ SkRRect rrect = iter.get()->getRRect();
+ rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
+ effect.reset(GrRRectEffect::Create(edgeType, rrect));
+ break;
+ }
+ case SkClipStack::Element::kRect_Type: {
+ SkRect rect = iter.get()->getRect();
+ rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
+ effect.reset(GrConvexPolyEffect::Create(edgeType, rect));
+ break;
+ }
+ default:
+ break;
+ }
+ if (effect) {
+ if (!setARE) {
+ are->set(fGpu->drawState());
+ setARE = true;
+ }
+ fGpu->drawState()->addCoverageEffect(effect);
+ } else {
+ failed = true;
+ break;
+ }
+ }
+ iter.next();
+ }
+
+ if (failed) {
+ are->set(NULL);
+ }
+
+ return !failed;
+}
+
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
@@ -156,59 +256,27 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
return true;
}
- // If there is only one clip element we check whether the draw's bounds are contained
- // fully within the clip. If not, we install an effect that handles the clip for some
- // cases.
- if (1 == elements.count() && SkRegion::kReplace_Op == elements.tail()->getOp()) {
- if (NULL != devBounds) {
- SkRect boundsInClipSpace = *devBounds;
- boundsInClipSpace.offset(SkIntToScalar(clipDataIn->fOrigin.fX),
- SkIntToScalar(clipDataIn->fOrigin.fY));
- if (elements.tail()->contains(boundsInClipSpace)) {
- fGpu->disableScissor();
- this->setGpuStencil();
- return true;
- }
- }
- Element::Type type = elements.tail()->getType();
- bool isAA = GR_AA_CLIP && elements.tail()->isAA();
- SkAutoTUnref<GrEffectRef> effect;
- if (SkClipStack::Element::kPath_Type == type) {
- const SkPath& path = elements.tail()->getPath();
- if (rt->isMultisampled()) {
- // A coverage effect for AA clipping won't play nicely with MSAA.
- if (!isAA) {
- SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
- SkIntToScalar(-clipDataIn->fOrigin.fY) };
- effect.reset(GrConvexPolyEffect::Create(kFillBW_GrEffectEdgeType,
- path, &offset));
- }
- } else {
- SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
+ // An element count of 4 was chosen because of the common pattern in Blink of:
+ // isect RR
+ // diff RR
+ // isect convex_poly
+ // isect convex_poly
+ // when drawing rounded div borders. This could probably be tuned based on a
+ // configuration's relative costs of switching RTs to generate a mask vs
+ // longer shaders.
+ if (elements.count() <= 4) {
+ SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
SkIntToScalar(-clipDataIn->fOrigin.fY) };
- GrEffectEdgeType type = isAA ? kFillAA_GrEffectEdgeType : kFillBW_GrEffectEdgeType;
- effect.reset(GrConvexPolyEffect::Create(type, path, &offset));
- }
- } else if (isAA && SkClipStack::Element::kRRect_Type == type && !rt->isMultisampled()) {
- const SkRRect& rrect = elements.tail()->getRRect();
- effect.reset(GrRRectEffect::Create(kFillAA_GrEffectEdgeType, rrect));
- } else if (isAA && SkClipStack::Element::kRect_Type == type && !rt->isMultisampled()) {
- // We only handle AA/non-MSAA rects here. Coverage effect AA isn't MSAA friendly and
- // non-AA rect clips are handled by the scissor.
- SkRect rect = elements.tail()->getRect();
- SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
- SkIntToScalar(-clipDataIn->fOrigin.fY) };
- rect.offset(offset);
- effect.reset(GrConvexPolyEffect::Create(kFillAA_GrEffectEdgeType, rect));
- // This should never fail.
- SkASSERT(effect);
- }
- if (effect) {
- are->set(fGpu->drawState());
- fGpu->drawState()->addCoverageEffect(effect);
+ if (elements.isEmpty() ||
+ this->installClipEffects(elements, are, clipToRTOffset, devBounds)) {
SkIRect scissorSpaceIBounds(clipSpaceIBounds);
scissorSpaceIBounds.offset(-clipDataIn->fOrigin);
- fGpu->enableScissor(scissorSpaceIBounds);
+ if (NULL == devBounds ||
+ !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) {
+ fGpu->enableScissor(scissorSpaceIBounds);
+ } else {
+ fGpu->disableScissor();
+ }
this->setGpuStencil();
return true;
}
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 3d34fb9555..17329108b3 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -105,6 +105,13 @@ private:
GrClipMaskCache fAACache; // cache for the AA path
+ // Attempts to install a series of coverage effects to implement the clip. Return indicates
+ // whether the element list was successfully converted to effects.
+ bool installClipEffects(const GrReducedClip::ElementList&,
+ GrDrawState::AutoRestoreEffects*,
+ const SkVector& clipOffset,
+ const SkRect* devBounds);
+
// Draws the clip into the stencil buffer
bool createStencilClipMask(int32_t elementsGenID,
GrReducedClip::InitialState initialState,
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 0793befb57..d24b45e10b 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -143,8 +143,8 @@ void GLAARectEffect::emitCode(GrGLShaderBuilder* builder,
builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
builder->fsCodeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
builder->fsCodeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
- builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > 0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
- builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > 0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
}
if (GrEffectEdgeTypeIsInverseFill(aare.getEdgeType())) {
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 5b755b350f..bc6abea547 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -67,7 +67,7 @@ const SkScalar RRectEffect::kRadiusMin = 0.5f;
GrEffectRef* RRectEffect::Create(GrEffectEdgeType edgeType,
RRectType rrType,
const SkRRect& rrect) {
- SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillBW_GrEffectEdgeType == edgeType);
+ SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdgeType == edgeType);
return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (edgeType, rrType, rrect))));
}
@@ -228,7 +228,7 @@ void GLRRectEffect::emitCode(GrGLShaderBuilder* builder,
break;
}
- if (kInverseFillBW_GrEffectEdgeType == rre.getEdgeType()) {
+ if (kInverseFillAA_GrEffectEdgeType == rre.getEdgeType()) {
builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
}
@@ -293,7 +293,7 @@ void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
//////////////////////////////////////////////////////////////////////////////
GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rrect) {
- if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillBW_GrEffectEdgeType != edgeType) {
+ if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) {
return NULL;
}
RRectEffect::RRectType rrtype;