diff options
author | bsalomon <bsalomon@google.com> | 2014-07-02 10:40:52 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-07-02 10:40:52 -0700 |
commit | a73218bbbdcbe458651d10815e8d3b73d71b8e11 (patch) | |
tree | 200245355cbabe5e3fb01bfc22ac4255f714fd58 /src/gpu | |
parent | b26130af2faf6a72b077c400557e638e89c339d4 (diff) |
Remove the AA requirement for selecting GrEffect-based clipping.
Also, optionally use the scissor for a bw clip rect element instead of an effect.
R=robertphillips@google.com
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/367013003
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 64 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 7 |
2 files changed, 56 insertions, 15 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index a878894c59..16ba613a76 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -110,7 +110,10 @@ bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { bool GrClipMaskManager::installClipEffects(const ElementList& elements, GrDrawState::AutoRestoreEffects* are, const SkVector& clipToRTOffset, - const SkRect* drawBounds) { + const SkRect* drawBounds, + SkIRect* scissorRect) { + + SkASSERT(NULL != scissorRect); GrDrawState* drawState = fGpu->drawState(); SkRect boundsInClipSpace; @@ -121,7 +124,11 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, are->set(drawState); GrRenderTarget* rt = drawState->getRenderTarget(); - ElementList::Iter iter(elements); + // We iterate from the top of the stack to the bottom. We do this because we select the first + // BW rectangle as the scissor. Clients performing hierarchical rendering tend to use smaller + // clips towards the top of the clip stack. Smaller scissor rects can help tiled architectures + // skip processing tiles for draws. + ElementList::Iter iter(elements, ElementList::Iter::kTail_IterStart); bool setARE = false; bool failed = false; @@ -157,7 +164,7 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, GrEffectEdgeType edgeType; if (GR_AA_CLIP && iter.get()->isAA()) { if (rt->isMultisampled()) { - // Coverage based AA clips don't place nicely with MSAA. + // Coverage based AA clips don't play nicely with MSAA. failed = true; break; } @@ -165,6 +172,8 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, } else { edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_GrEffectEdgeType; } + // We don't want to exit if we convert a BW rect clip to a scissor. + bool failIfNoEffect = true; SkAutoTUnref<GrEffectRef> effect; switch (iter.get()->getType()) { case SkClipStack::Element::kPath_Type: @@ -180,7 +189,14 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, case SkClipStack::Element::kRect_Type: { SkRect rect = iter.get()->getRect(); rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); - effect.reset(GrConvexPolyEffect::Create(edgeType, rect)); + if (kFillBW_GrEffectEdgeType == edgeType && scissorRect->isEmpty()) { + // This is OK because we only allow clip operations that shrink the clip + // to be implemented as effects. + rect.roundOut(scissorRect); + failIfNoEffect = false; + } else { + effect.reset(GrConvexPolyEffect::Create(edgeType, rect)); + } break; } default: @@ -192,12 +208,12 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, setARE = true; } fGpu->drawState()->addCoverageEffect(effect); - } else { + } else if (failIfNoEffect) { failed = true; break; } } - iter.next(); + iter.prev(); } if (failed) { @@ -207,6 +223,13 @@ bool GrClipMaskManager::installClipEffects(const ElementList& elements, return !failed; } +static inline bool rect_contains_irect(const SkIRect ir, const SkRect& r) { + SkASSERT(!ir.isEmpty()); + SkASSERT(!r.isEmpty()); + return ir.fLeft <= r.fLeft && ir.fTop <= r.fTop && + ir.fRight >= r.fRight && ir.fBottom >= r.fBottom; +} + //////////////////////////////////////////////////////////////////////////////// // sort out what kind of clip mask needs to be created: alpha, stencil, // scissor, or entirely software @@ -263,17 +286,32 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, // configuration's relative costs of switching RTs to generate a mask vs // longer shaders. if (elements.count() <= 4) { + SkIRect scissorRect; + scissorRect.setEmpty(); SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), SkIntToScalar(-clipDataIn->fOrigin.fY) }; if (elements.isEmpty() || - (requiresAA && this->installClipEffects(elements, are, clipToRTOffset, devBounds))) { - SkIRect scissorSpaceIBounds(clipSpaceIBounds); - scissorSpaceIBounds.offset(-clipDataIn->fOrigin); - if (NULL == devBounds || - !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { - fGpu->enableScissor(scissorSpaceIBounds); + this->installClipEffects(elements, are, clipToRTOffset, devBounds, &scissorRect)) { + if (scissorRect.isEmpty()) { + // We may still want to use a scissor, especially on tiled architectures. + scissorRect = clipSpaceIBounds; + scissorRect.offset(-clipDataIn->fOrigin); + if (NULL == devBounds || + !rect_contains_irect(scissorRect, *devBounds)) { + fGpu->enableScissor(scissorRect); + } else { + // When the vertices that will be rendered fit fully inside the clip's bounds + // then providing the scissor rect will not help the driver eliminate tiles + // from consideration for the draw, but changing the scissor will cause + // state changes between draws. + fGpu->disableScissor(); + } } else { - fGpu->disableScissor(); + scissorRect.fLeft = SkTMax(0, scissorRect.fLeft); + scissorRect.fTop = SkTMax(0, scissorRect.fTop); + scissorRect.fRight = SkTMin(rt->width(), scissorRect.fRight); + scissorRect.fBottom = SkTMin(rt->height(), scissorRect.fBottom); + fGpu->enableScissor(scissorRect); } this->setGpuStencil(); return true; diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index c3a21fd8a2..974c217705 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -106,11 +106,14 @@ 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. + // whether the element list was successfully converted to effects. One of the elements may + // be selected to use the scissor. If so scissorRect will be updated to a valid rectangle + // that the caller should set as the scissor rect. If not, scissorRect won't be modified. bool installClipEffects(const GrReducedClip::ElementList&, GrDrawState::AutoRestoreEffects*, const SkVector& clipOffset, - const SkRect* devBounds); + const SkRect* devBounds, + SkIRect* scissorRect); // Draws the clip into the stencil buffer bool createStencilClipMask(int32_t elementsGenID, |