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

Commit 64d3b59c authored by Alec Mouri's avatar Alec Mouri
Browse files

Add a stricter check for resetting all cached sets.

Presently cached sets are reset if the previously seen layer geometry
hashed to the same value as the incoming layer geometry. But because
hashing does not guarantee uniqueness, this check is not inclusive
enough to check for invalidating the cached sets since it does not
correctly invalidate when there is a colliding geometry.

Instead, check for equality of the LayerState geometries directly, which
is computationally equivalent to computing the hash but guarantees that
unique geometries do not equal each other.

Bug: 185728087
Test: libcompositionengine_test
Test: camera app no longer crashes when switching between cameras.
Change-Id: I2a5e918464690d7e7f54ecd73b8eb7631d2aed9c
parent f7891609
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ public:
    const sp<Fence>& getDrawFence() const { return mDrawFence; }
    const ProjectionSpace& getOutputSpace() const { return mOutputSpace; }
    ui::Dataspace getOutputDataspace() const { return mOutputDataspace; }
    const std::vector<Layer>& getConstituentLayers() const { return mLayers; }

    NonBufferHash getNonBufferHash() const;

+33 −1
Original line number Diff line number Diff line
@@ -27,12 +27,44 @@ using namespace std::chrono_literals;

namespace android::compositionengine::impl::planner {

namespace {

// True if the underlying layer stack is the same modulo state that would be expected to be
// different like specific buffers, false otherwise.
bool isSameStack(const std::vector<const LayerState*>& incomingLayers,
                 const std::vector<CachedSet>& cachedSets) {
    std::vector<const LayerState*> existingLayers;
    for (auto& cachedSet : cachedSets) {
        for (auto& layer : cachedSet.getConstituentLayers()) {
            existingLayers.push_back(layer.getState());
        }
    }

    if (incomingLayers.size() != existingLayers.size()) {
        return false;
    }

    for (size_t i = 0; i < incomingLayers.size(); i++) {
        if (incomingLayers[i]->getDifferingFields(*(existingLayers[i])) != LayerStateField::None) {
            return false;
        }
    }
    return true;
}

} // namespace

NonBufferHash Flattener::flattenLayers(const std::vector<const LayerState*>& layers,
                                       NonBufferHash hash, time_point now) {
    const size_t unflattenedDisplayCost = calculateDisplayCost(layers);
    mUnflattenedDisplayCost += unflattenedDisplayCost;

    if (mCurrentGeometry != hash) {
    // We invalidate the layer cache if:
    // 1. We're not tracking any layers, or
    // 2. The last seen hashed geometry changed between frames, or
    // 3. A stricter equality check demonstrates that the layer stack really did change, since the
    // hashed geometry does not guarantee uniqueness.
    if (mCurrentGeometry != hash || (!mLayers.empty() && !isSameStack(layers, mLayers))) {
        resetActivities(hash, now);
        mFlattenedDisplayCost += unflattenedDisplayCost;
        return hash;