Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9ee5508 authored by John Reck's avatar John Reck
Browse files

Reduce, reuse, recycle SNAPSHOTS!

Shaves like, 1 whole us off of reset

Change-Id: I459370448583d5e22fd302ba1353319564a814be
parent 9ad05de2
Loading
Loading
Loading
Loading
+53 −7
Original line number Diff line number Diff line
@@ -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() {
+17 −7
Original line number Diff line number Diff line
@@ -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

+3 −3
Original line number Diff line number Diff line
@@ -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());
+3 −3
Original line number Diff line number Diff line
@@ -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.