Reduce, reuse, recycle SNAPSHOTS!
Shaves like, 1 whole us off of reset
Change-Id: I459370448583d5e22fd302ba1353319564a814be
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index c128ca7..eca71c6 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -28,10 +28,21 @@
, 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 @@
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 @@
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 @@
* 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 @@
* 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 f0fb9ba..be57f44 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 @@
class CanvasState {
public:
CanvasState(CanvasStateClient& renderer);
+ ~CanvasState();
/**
* Initializes the first snapshot, computing the projection matrix,
@@ -157,11 +158,15 @@
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 @@
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 4d60b8d..0a58f4b 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -44,7 +44,7 @@
* 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 @@
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 @@
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 cf8f11c..aeeda96 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -83,11 +83,11 @@
* 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 @@
/**
* Previous snapshot.
*/
- sp<Snapshot> previous;
+ Snapshot* previous;
/**
* A pointer to the currently active layer.