diff options
author | Rob Tsuk <robtsuk@google.com> | 2015-01-06 13:22:54 -0800 |
---|---|---|
committer | Rob Tsuk <robtsuk@google.com> | 2015-01-14 17:24:58 -0800 |
commit | 487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8 (patch) | |
tree | 6515f9b52f874f5f076a25df83a353de10a3da14 /libs/hwui/Snapshot.cpp | |
parent | 382d6a9ed2360ceb462ea46a60f0f106fdb52540 (diff) | |
download | frameworks_base-487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8.zip frameworks_base-487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8.tar.gz frameworks_base-487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8.tar.bz2 |
Clipping performance improvements
Create a ClipArea class to handle tracking clip regions. This class can
select the most efficient implementation depending on the types of
clipping presented.
ClipArea re-used the rectangle and region-based clipping
implementations as well as adding a "list of rotated rectangles"
approach that is more efficient for rotated views with children.
Change-Id: I2133761a2462ebc0852b394220e265974b3086f0
Diffstat (limited to 'libs/hwui/Snapshot.cpp')
-rw-r--r-- | libs/hwui/Snapshot.cpp | 108 |
1 files changed, 19 insertions, 89 deletions
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index d4ca99e..49fb4ba 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -35,11 +35,10 @@ Snapshot::Snapshot() , invisible(false) , empty(false) , alpha(1.0f) - , roundRectClipState(nullptr) { + , roundRectClipState(nullptr) + , mClipArea(&mClipAreaRoot) { transform = &mTransformRoot; - clipRect = &mClipRectRoot; region = nullptr; - clipRegion = &mClipRegionRoot; } /** @@ -55,6 +54,7 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) , empty(false) , alpha(s->alpha) , roundRectClipState(s->roundRectClipState) + , mClipArea(nullptr) , mViewportData(s->mViewportData) , mRelativeLightCenter(s->mRelativeLightCenter) { if (saveFlags & SkCanvas::kMatrix_SaveFlag) { @@ -65,15 +65,10 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) } if (saveFlags & SkCanvas::kClip_SaveFlag) { - mClipRectRoot.set(*s->clipRect); - clipRect = &mClipRectRoot; - if (!s->clipRegion->isEmpty()) { - mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op); - } - clipRegion = &mClipRegionRoot; + mClipAreaRoot = s->getClipArea(); + mClipArea = &mClipAreaRoot; } else { - clipRect = s->clipRect; - clipRegion = s->clipRegion; + mClipArea = s->mClipArea; } if (s->flags & Snapshot::kFlagFboTarget) { @@ -88,88 +83,23 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) // Clipping /////////////////////////////////////////////////////////////////////////////// -void Snapshot::ensureClipRegion() { - if (clipRegion->isEmpty()) { - clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); - } -} - -void Snapshot::copyClipRectFromRegion() { - if (!clipRegion->isEmpty()) { - const SkIRect& bounds = clipRegion->getBounds(); - clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); - - if (clipRegion->isRect()) { - clipRegion->setEmpty(); - } - } else { - clipRect->setEmpty(); - } -} - -bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) { - SkIRect tmp; - tmp.set(left, top, right, bottom); - clipRegion->op(tmp, op); - copyClipRectFromRegion(); - return true; -} - bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) { - ensureClipRegion(); - clipRegion->op(region, op); - copyClipRectFromRegion(); flags |= Snapshot::kFlagClipSet; - return true; + return mClipArea->clipRegion(region, op); } bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) { - Rect r(left, top, right, bottom); - transform->mapRect(r); - return clipTransformed(r, op); + flags |= Snapshot::kFlagClipSet; + return mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op); } -bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) { - bool clipped = false; - - switch (op) { - case SkRegion::kIntersect_Op: { - if (CC_UNLIKELY(!clipRegion->isEmpty())) { - ensureClipRegion(); - clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op); - } else { - clipped = clipRect->intersect(r); - if (!clipped) { - clipRect->setEmpty(); - clipped = true; - } - } - break; - } - case SkRegion::kReplace_Op: { - setClip(r.left, r.top, r.right, r.bottom); - clipped = true; - break; - } - default: { - ensureClipRegion(); - clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op); - break; - } - } - - if (clipped) { - flags |= Snapshot::kFlagClipSet; - } - - return clipped; +bool Snapshot::clipPath(const SkPath& path, SkRegion::Op op) { + flags |= Snapshot::kFlagClipSet; + return mClipArea->clipPathWithTransform(path, transform, op); } void Snapshot::setClip(float left, float top, float right, float bottom) { - clipRect->set(left, top, right, bottom); - if (!clipRegion->isEmpty()) { - clipRegion->setEmpty(); - } + mClipArea->setClip(left, top, right, bottom); flags |= Snapshot::kFlagClipSet; } @@ -181,7 +111,7 @@ const Rect& Snapshot::getLocalClip() { mat4 inverse; inverse.loadInverse(*transform); - mLocalClip.set(*clipRect); + mLocalClip.set(mClipArea->getClipRect()); inverse.mapRect(mLocalClip); return mLocalClip; @@ -191,8 +121,7 @@ void Snapshot::resetClip(float left, float top, float right, float bottom) { // TODO: This is incorrect, when we start rendering into a new layer, // we may have to modify the previous snapshot's clip rect and clip // region if the previous restore() call did not restore the clip - clipRect = &mClipRectRoot; - clipRegion = &mClipRegionRoot; + mClipArea = &mClipAreaRoot; setClip(left, top, right, bottom); } @@ -219,7 +148,7 @@ void Snapshot::resetTransform(float x, float y, float z) { void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius, bool highPriority) { if (bounds.isEmpty()) { - clipRect->setEmpty(); + mClipArea->setEmpty(); return; } @@ -272,9 +201,10 @@ bool Snapshot::isIgnored() const { void Snapshot::dump() const { ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d", - this, flags, previous.get(), getViewportHeight(), isIgnored(), clipRegion && !clipRegion->isEmpty()); + this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple()); + const Rect& clipRect(mClipArea->getClipRect()); ALOGD(" ClipRect (at %p) %.1f %.1f %.1f %.1f", - clipRect, clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); + clipRect, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); ALOGD(" Transform (at %p):", transform); transform->dump(); } |