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

Commit f0bd6f6c authored by Vishnu Nair's avatar Vishnu Nair Committed by Android (Google) Code Review
Browse files

Merge "SF: More frontend fixes"

parents 44e355f7 80a5a708
Loading
Loading
Loading
Loading
+23 −21
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define LOG_TAG "LayerHierarchy"

#include "LayerHierarchy.h"
#include "LayerLog.h"
#include "SwapErase.h"

namespace android::surfaceflinger::frontend {
@@ -259,6 +260,7 @@ void LayerHierarchyBuilder::onLayerAdded(RequestedLayerState* layer) {
}

void LayerHierarchyBuilder::onLayerDestroyed(RequestedLayerState* layer) {
    LLOGV(layer->id, "");
    LayerHierarchy* hierarchy = getHierarchyFromId(layer->id, /*crashOnFailure=*/false);
    if (!hierarchy) {
        // Layer was never part of the hierarchy if it was created and destroyed in the same
@@ -408,29 +410,32 @@ std::string LayerHierarchy::TraversalPath::toString() const {
    if (id == UNASSIGNED_LAYER_ID) {
        return "TraversalPath{ROOT}";
    }
    std::string debugString = "TraversalPath{.id = " + std::to_string(id);
    std::stringstream ss;
    ss << "TraversalPath{.id = " << id;

    if (!mirrorRootIds.empty()) {
        debugString += ", .mirrorRootIds=";
        for (auto rootId : mirrorRootIds) {
            debugString += std::to_string(rootId) + ",";
        }
    if (mirrorRootId != UNASSIGNED_LAYER_ID) {
        ss << ", .mirrorRootId=" << mirrorRootId;
    }

    if (!relativeRootIds.empty()) {
        debugString += ", .relativeRootIds=";
        ss << ", .relativeRootIds=";
        for (auto rootId : relativeRootIds) {
            debugString += std::to_string(rootId) + ",";
            ss << rootId << ",";
        }
    }

    if (hasRelZLoop()) {
        debugString += ", hasRelZLoop=true invalidRelativeRootId=";
        debugString += std::to_string(invalidRelativeRootId) + ",";
        ss << "hasRelZLoop=true invalidRelativeRootId=" << invalidRelativeRootId << ",";
    }
    ss << "}";
    return ss.str();
}

    debugString += "}";
    return debugString;
LayerHierarchy::TraversalPath LayerHierarchy::TraversalPath::getMirrorRoot() const {
    LOG_ALWAYS_FATAL_IF(!isClone(), "Cannot get mirror root of a non cloned node");
    TraversalPath mirrorRootPath = *this;
    mirrorRootPath.id = mirrorRootId;
    return mirrorRootPath;
}

// Helper class to update a passed in TraversalPath when visiting a child. When the object goes out
@@ -438,16 +443,13 @@ std::string LayerHierarchy::TraversalPath::toString() const {
LayerHierarchy::ScopedAddToTraversalPath::ScopedAddToTraversalPath(TraversalPath& traversalPath,
                                                                   uint32_t layerId,
                                                                   LayerHierarchy::Variant variant)
      : mTraversalPath(traversalPath),
        mParentId(traversalPath.id),
        mParentVariant(traversalPath.variant),
        mParentDetached(traversalPath.detached) {
      : mTraversalPath(traversalPath), mParentPath(traversalPath) {
    // Update the traversal id with the child layer id and variant. Parent id and variant are
    // stored to reset the id upon destruction.
    traversalPath.id = layerId;
    traversalPath.variant = variant;
    if (variant == LayerHierarchy::Variant::Mirror) {
        traversalPath.mirrorRootIds.emplace_back(layerId);
        traversalPath.mirrorRootId = layerId;
    } else if (variant == LayerHierarchy::Variant::Relative) {
        if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(),
                      layerId) != traversalPath.relativeRootIds.end()) {
@@ -462,16 +464,16 @@ LayerHierarchy::ScopedAddToTraversalPath::~ScopedAddToTraversalPath() {
    // Reset the traversal id to its original parent state using the state that was saved in
    // the constructor.
    if (mTraversalPath.variant == LayerHierarchy::Variant::Mirror) {
        mTraversalPath.mirrorRootIds.pop_back();
        mTraversalPath.mirrorRootId = mParentPath.mirrorRootId;
    } else if (mTraversalPath.variant == LayerHierarchy::Variant::Relative) {
        mTraversalPath.relativeRootIds.pop_back();
    }
    if (mTraversalPath.invalidRelativeRootId == mTraversalPath.id) {
        mTraversalPath.invalidRelativeRootId = UNASSIGNED_LAYER_ID;
    }
    mTraversalPath.id = mParentId;
    mTraversalPath.variant = mParentVariant;
    mTraversalPath.detached = mParentDetached;
    mTraversalPath.id = mParentPath.id;
    mTraversalPath.variant = mParentPath.variant;
    mTraversalPath.detached = mParentPath.detached;
}

} // namespace android::surfaceflinger::frontend
+25 −6
Original line number Diff line number Diff line
@@ -50,12 +50,32 @@ public:
        ftl_last = Mirror,
    };
    // Represents a unique path to a node.
    // The layer hierarchy is represented as a graph. Each node can be visited by multiple parents.
    // This allows us to represent mirroring in an efficient way. See the example below:
    // root
    // ├─ A {Traversal path id = 1}
    // ├─ B {Traversal path id = 2}
    // │  ├─ C {Traversal path id = 3}
    // │  ├─ D {Traversal path id = 4}
    // │  └─ E {Traversal path id = 5}
    // ├─ F (Mirrors B) {Traversal path id = 6}
    // └─ G (Mirrors F) {Traversal path id = 7}
    //
    // C, D and E can be traversed via B or via F then B or via G then F then B.
    // Depending on how the node is reached, its properties such as geometry or visibility might be
    // different. And we can uniquely identify the node by keeping track of the nodes leading up to
    // it. But to be more efficient we only need to track the nodes id and the top mirror root path.
    // So C for example, would have the following unique traversal paths:
    //  - {Traversal path id = 3}
    //  - {Traversal path id = 3, mirrorRootId = 6}
    //  - {Traversal path id = 3, mirrorRootId = 7}

    struct TraversalPath {
        uint32_t id;
        LayerHierarchy::Variant variant;
        // Mirrored layers can have a different geometry than their parents so we need to track
        // the mirror roots in the traversal.
        ftl::SmallVector<uint32_t, 5> mirrorRootIds;
        uint32_t mirrorRootId = UNASSIGNED_LAYER_ID;
        // Relative layers can be visited twice, once by their parent and then once again by
        // their relative parent. We keep track of the roots here to detect any loops in the
        // hierarchy. If a relative root already exists in the list while building the
@@ -73,10 +93,11 @@ public:
        // Returns true if the node or its parents are not Detached.
        bool isAttached() const { return !detached; }
        // Returns true if the node is a clone.
        bool isClone() const { return !mirrorRootIds.empty(); }
        bool isClone() const { return mirrorRootId != UNASSIGNED_LAYER_ID; }
        TraversalPath getMirrorRoot() const;

        bool operator==(const TraversalPath& other) const {
            return id == other.id && mirrorRootIds == other.mirrorRootIds;
            return id == other.id && mirrorRootId == other.mirrorRootId;
        }
        std::string toString() const;

@@ -93,9 +114,7 @@ public:

    private:
        TraversalPath& mTraversalPath;
        uint32_t mParentId;
        LayerHierarchy::Variant mParentVariant;
        bool mParentDetached;
        TraversalPath mParentPath;
    };
    LayerHierarchy(RequestedLayerState* layer);

+3 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "LayerLifecycleManager.h"
#include "Layer.h" // temporarily needed for LayerHandle
#include "LayerHandle.h"
#include "LayerLog.h"
#include "SwapErase.h"

namespace android::surfaceflinger::frontend {
@@ -36,6 +37,7 @@ void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayer
    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
    for (auto& newLayer : newLayers) {
        RequestedLayerState& layer = *newLayer.get();
        LLOGV(layer.id, "%s layer %s", __func__, layer.getDebugStringShort().c_str());
        auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
        if (!inserted) {
            LOG_ALWAYS_FATAL("Duplicate layer id %d found. Existing layer: %s", layer.id,
@@ -146,7 +148,7 @@ void LayerLifecycleManager::onHandlesDestroyed(const std::vector<uint32_t>& dest
    while (it != mLayers.end()) {
        RequestedLayerState* layer = it->get();
        if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
            ALOGV("%s destroyed layer %s", __func__, layer->getDebugStringShort().c_str());
            LLOGV(layer->id, "destroyed layer %s", layer->getDebugStringShort().c_str());
            std::iter_swap(it, mLayers.end() - 1);
            mDestroyedLayers.emplace_back(std::move(mLayers.back()));
            if (it == mLayers.end() - 1) {
+19 −10
Original line number Diff line number Diff line
@@ -259,8 +259,8 @@ void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFram
    }
}

void updateVisibility(LayerSnapshot& snapshot) {
    snapshot.isVisible = snapshot.getIsVisible();
void updateVisibility(LayerSnapshot& snapshot, bool visible) {
    snapshot.isVisible = visible;

    // TODO(b/238781169) we are ignoring this compat for now, since we will have
    // to remove any optimization based on visibility.
@@ -273,9 +273,9 @@ void updateVisibility(LayerSnapshot& snapshot) {
    // We are just using these layers for occlusion detection in
    // InputDispatcher, and obviously if they aren't visible they can't occlude
    // anything.
    const bool visible =
    const bool visibleForInput =
            (snapshot.inputInfo.token != nullptr) ? snapshot.canReceiveInput() : snapshot.isVisible;
    snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visible);
    snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
}

bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
@@ -521,7 +521,7 @@ void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
                }

                if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
                    updateVisibility(*snapshot);
                    updateVisibility(*snapshot, snapshot->getIsVisible());
                    size_t oldZ = snapshot->globalZ;
                    size_t newZ = globalZ++;
                    snapshot->globalZ = newZ;
@@ -539,7 +539,8 @@ void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
    mNumInterestingSnapshots = (int)globalZ;
    while (globalZ < mSnapshots.size()) {
        mSnapshots[globalZ]->globalZ = globalZ;
        updateVisibility(*mSnapshots[globalZ]);
        /* mark unreachable snapshots as explicitly invisible */
        updateVisibility(*mSnapshots[globalZ], false);
        globalZ++;
    }
}
@@ -634,11 +635,15 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a
    const bool forceUpdate = newSnapshot || args.forceUpdate ||
            snapshot.changes.any(RequestedLayerState::Changes::Visibility |
                                 RequestedLayerState::Changes::Created);
    snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
            ? parentSnapshot.outputFilter.layerStack
            : requested.layerStack;

    uint32_t displayRotationFlags =
            getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);

    // always update the buffer regardless of visibility
    if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES) {
    if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
        snapshot.acquireFence =
                (requested.externalTexture &&
                 requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
@@ -727,9 +732,13 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a
    if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
        snapshot.color.rgb = requested.getColor().rgb;
        snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
        snapshot.backgroundBlurRadius =
                args.supportsBlur ? static_cast<int>(requested.backgroundBlurRadius) : 0;
        snapshot.backgroundBlurRadius = args.supportsBlur
                ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
                : 0;
        snapshot.blurRegions = requested.blurRegions;
        for (auto& region : snapshot.blurRegions) {
            region.alpha = region.alpha * snapshot.color.a;
        }
        snapshot.hdrMetadata = requested.hdrMetadata;
    }

@@ -965,7 +974,7 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
    // touches from going outside the cloned area.
    if (path.isClone()) {
        snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
        auto clonedRootSnapshot = getSnapshot(path.mirrorRootIds.back());
        auto clonedRootSnapshot = getSnapshot(path.getMirrorRoot());
        if (clonedRootSnapshot) {
            const Rect rect =
                    displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
+2 −2
Original line number Diff line number Diff line
@@ -115,8 +115,8 @@ private:
    struct TraversalPathHash {
        std::size_t operator()(const LayerHierarchy::TraversalPath& key) const {
            uint32_t hashCode = key.id * 31;
            for (auto mirrorRoot : key.mirrorRootIds) {
                hashCode += mirrorRoot * 31;
            if (key.mirrorRootId != UNASSIGNED_LAYER_ID) {
                hashCode += key.mirrorRootId * 31;
            }
            return std::hash<size_t>{}(hashCode);
        }
Loading