aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2014-07-02 10:40:52 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-02 10:40:52 -0700
commita73218bbbdcbe458651d10815e8d3b73d71b8e11 (patch)
tree200245355cbabe5e3fb01bfc22ac4255f714fd58 /src/gpu
parentb26130af2faf6a72b077c400557e638e89c339d4 (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.cpp64
-rw-r--r--src/gpu/GrClipMaskManager.h7
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,