Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Unified Diff: src/gpu/GrClipMaskManager.cpp

Issue 188693008: Implement the clip as 4 or fewer GrEffects when possible. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: fix comment spelling Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrClipMaskManager.h ('k') | src/gpu/effects/GrConvexPolyEffect.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrClipMaskManager.cpp
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index e24c759688ef2672af7528aa84a2355aac672a1f..96f4b209e385944584f1339d87bc5bdd57e6b82b 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;
}
« no previous file with comments | « src/gpu/GrClipMaskManager.h ('k') | src/gpu/effects/GrConvexPolyEffect.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698