diff options
| -rw-r--r-- | libs/hwui/CanvasState.cpp | 60 | ||||
| -rw-r--r-- | libs/hwui/CanvasState.h | 24 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.h | 6 |
4 files changed, 76 insertions, 20 deletions
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp index c128ca775155..eca71c6e0e8d 100644 --- a/libs/hwui/CanvasState.cpp +++ b/libs/hwui/CanvasState.cpp @@ -28,10 +28,21 @@ CanvasState::CanvasState(CanvasStateClient& renderer) , mWidth(-1) , mHeight(-1) , mSaveCount(1) - , mFirstSnapshot(new Snapshot) , mCanvas(renderer) - , mSnapshot(mFirstSnapshot) { + , mSnapshot(&mFirstSnapshot) { +} + +CanvasState::~CanvasState() { + // First call freeSnapshot on all but mFirstSnapshot + // to invoke all the dtors + freeAllSnapshots(); + // Now actually release the memory + while (mSnapshotPool) { + void* temp = mSnapshotPool; + mSnapshotPool = mSnapshotPool->previous; + free(temp); + } } void CanvasState::initializeSaveStack( @@ -41,11 +52,12 @@ void CanvasState::initializeSaveStack( if (mWidth != viewportWidth || mHeight != viewportHeight) { mWidth = viewportWidth; mHeight = viewportHeight; - mFirstSnapshot->initializeViewport(viewportWidth, viewportHeight); + mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight); mCanvas.onViewportInitialized(); } - mSnapshot = new Snapshot(mFirstSnapshot, + freeAllSnapshots(); + mSnapshot = allocSnapshot(&mFirstSnapshot, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom); mSnapshot->fbo = mCanvas.getTargetFbo(); @@ -53,6 +65,38 @@ void CanvasState::initializeSaveStack( mSaveCount = 1; } +Snapshot* CanvasState::allocSnapshot(Snapshot* previous, int savecount) { + void* memory; + if (mSnapshotPool) { + memory = mSnapshotPool; + mSnapshotPool = mSnapshotPool->previous; + mSnapshotPoolCount--; + } else { + memory = malloc(sizeof(Snapshot)); + } + return new (memory) Snapshot(previous, savecount); +} + +void CanvasState::freeSnapshot(Snapshot* snapshot) { + snapshot->~Snapshot(); + // Arbitrary number, just don't let this grown unbounded + if (mSnapshotPoolCount > 10) { + free((void*) snapshot); + } else { + snapshot->previous = mSnapshotPool; + mSnapshotPool = snapshot; + mSnapshotPoolCount++; + } +} + +void CanvasState::freeAllSnapshots() { + while (mSnapshot != &mFirstSnapshot) { + Snapshot* temp = mSnapshot; + mSnapshot = mSnapshot->previous; + freeSnapshot(temp); + } +} + /////////////////////////////////////////////////////////////////////////////// // Save (layer) /////////////////////////////////////////////////////////////////////////////// @@ -64,7 +108,7 @@ void CanvasState::initializeSaveStack( * stack, and ensures restoreToCount() doesn't call back into subclass overrides. */ int CanvasState::saveSnapshot(int flags) { - mSnapshot = new Snapshot(mSnapshot, flags); + mSnapshot = allocSnapshot(mSnapshot, flags); return mSaveCount++; } @@ -76,14 +120,16 @@ int CanvasState::save(int flags) { * Guaranteed to restore without side-effects. */ void CanvasState::restoreSnapshot() { - sp<Snapshot> toRemove = mSnapshot; - sp<Snapshot> toRestore = mSnapshot->previous; + Snapshot* toRemove = mSnapshot; + Snapshot* toRestore = mSnapshot->previous; mSaveCount--; mSnapshot = toRestore; // subclass handles restore implementation mCanvas.onSnapshotRestored(*toRemove, *toRestore); + + freeSnapshot(toRemove); } void CanvasState::restore() { diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h index f0fb9ba8b324..be57f44210ef 100644 --- a/libs/hwui/CanvasState.h +++ b/libs/hwui/CanvasState.h @@ -17,12 +17,12 @@ #ifndef ANDROID_HWUI_CANVAS_STATE_H #define ANDROID_HWUI_CANVAS_STATE_H +#include "Snapshot.h" + #include <SkMatrix.h> #include <SkPath.h> #include <SkRegion.h> -#include "Snapshot.h" - namespace android { namespace uirenderer { @@ -74,6 +74,7 @@ public: class CanvasState { public: CanvasState(CanvasStateClient& renderer); + ~CanvasState(); /** * Initializes the first snapshot, computing the projection matrix, @@ -157,11 +158,15 @@ public: int getHeight() const { return mHeight; } bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); } - inline const Snapshot* currentSnapshot() const { return mSnapshot.get(); } - inline Snapshot* writableSnapshot() { return mSnapshot.get(); } - inline const Snapshot* firstSnapshot() const { return mFirstSnapshot.get(); } + inline const Snapshot* currentSnapshot() const { return mSnapshot; } + inline Snapshot* writableSnapshot() { return mSnapshot; } + inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; } private: + Snapshot* allocSnapshot(Snapshot* previous, int savecount); + void freeSnapshot(Snapshot* snapshot); + void freeAllSnapshots(); + /// indicates that the clip has been changed since the last time it was consumed bool mDirtyClip; @@ -172,13 +177,18 @@ private: int mSaveCount; /// Base state - sp<Snapshot> mFirstSnapshot; + Snapshot mFirstSnapshot; /// Host providing callbacks CanvasStateClient& mCanvas; /// Current state - sp<Snapshot> mSnapshot; + Snapshot* mSnapshot; + + // Pool of allocated snapshots to re-use + // NOTE: The dtors have already been invoked! + Snapshot* mSnapshotPool = nullptr; + int mSnapshotPoolCount = 0; }; // class CanvasState diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index 4d60b8dd0e7c..0a58f4b42e4c 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -44,7 +44,7 @@ Snapshot::Snapshot() * Copies the specified snapshot/ The specified snapshot is stored as * the previous snapshot. */ -Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) +Snapshot::Snapshot(Snapshot* s, int saveFlags) : flags(0) , previous(s) , layer(s->layer) @@ -148,7 +148,7 @@ void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const { const Snapshot* current = this; do { snapshotList.push(current); - current = current->previous.get(); + current = current->previous; } while (current); // traverse the list, adding in each transform that contributes to the total transform @@ -240,7 +240,7 @@ 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(), !mClipArea->isSimple()); + this, flags, previous, getViewportHeight(), isIgnored(), !mClipArea->isSimple()); const Rect& clipRect(mClipArea->getClipRect()); ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d", clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple()); diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index cf8f11c80058..aeeda965c48f 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -83,11 +83,11 @@ public: * Each snapshot has a link to a previous snapshot, indicating the previous * state of the renderer. */ -class Snapshot: public LightRefBase<Snapshot> { +class Snapshot { public: Snapshot(); - Snapshot(const sp<Snapshot>& s, int saveFlags); + Snapshot(Snapshot* s, int saveFlags); /** * Various flags set on ::flags. @@ -229,7 +229,7 @@ public: /** * Previous snapshot. */ - sp<Snapshot> previous; + Snapshot* previous; /** * A pointer to the currently active layer. |