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

Commit afb9c866 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge "Reduce, reuse, recycle SNAPSHOTS!"

parents f4755895 d9ee5508
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.