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

Commit 4cff1c71 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement stop layers" into main

parents 9bf557f6 42473a6a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -919,6 +919,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const {
    if (other.what & eLutsChanged) diff |= eLutsChanged;
    CHECK_DIFF(diff, ePictureProfileHandleChanged, other, pictureProfileHandle);
    CHECK_DIFF(diff, eAppContentPriorityChanged, other, appContentPriority);
    if (other.what & eStopLayerChanged) diff |= eStopLayerChanged;

    return diff;
}
+1 −0
Original line number Diff line number Diff line
@@ -254,6 +254,7 @@ struct layer_state_t {
        eClientDrawnCornerRadiusChanged = 0x200000'00000000,
        eBorderSettingsChanged = 0x400000'00000000,
        eBoxShadowSettingsChanged = 0x800000'00000000,
        eStopLayerChanged = 0x1000000'00000000,
    };

    layer_state_t();
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct LayerCreationArgs {
    ui::LayerStack layerStackToMirror = ui::UNASSIGNED_LAYER_STACK;
    uint32_t parentId = UNASSIGNED_LAYER_ID;
    uint32_t layerIdToMirror = UNASSIGNED_LAYER_ID;
    uint32_t stopLayerId = UNASSIGNED_LAYER_ID;
    std::atomic<int32_t>* pendingBuffers = 0;
};

+100 −0
Original line number Diff line number Diff line
@@ -450,11 +450,17 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
        LayerHierarchy::TraversalPath childPath =
                root.makeChild(args.root.getLayer()->id, LayerHierarchy::Variant::Attached);
        updateSnapshotsInHierarchy(args, args.root, childPath, rootSnapshot, /*depth=*/0);
        if (FlagManager::getInstance().stop_layer()) {
            applyStopLayers(args.root, childPath);
        }
    } else {
        for (auto& [childHierarchy, variant] : args.root.mChildren) {
            LayerHierarchy::TraversalPath childPath =
                    root.makeChild(childHierarchy->getLayer()->id, variant);
            updateSnapshotsInHierarchy(args, *childHierarchy, childPath, rootSnapshot, /*depth=*/0);
            if (FlagManager::getInstance().stop_layer()) {
                applyStopLayers(*childHierarchy, childPath);
            }
        }
    }

@@ -1397,4 +1403,98 @@ void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
    }
}

// Apply stop layers to the hierarchy.
//
// If layer X specifies stop layer Y, then any layer within X's subhierarchy that is z-ordered
// above Y is hidden. The stop layer itself, layer Y, is also hidden.
//
// This works by traversing the hierarchy in z-order. When a layer that specifies a stop layer is
// encountered, the specified stop layer is pushed to the stopLayer stack, the subhierarchy is
// traversed, then the stop layer is popped from the stack. If a layer whose id is stored in the
// stop layer stack is encountered during traversal, it is added to the activeStopLayers set. Any
// layer visited while the activeStopLayer set is non-empty is hidden. When an element is popped
// from the stopLayer stack, any active stop layers that are no longer in the stopLayer stack are
// removed from the activeStopLayers set.
void LayerSnapshotBuilder::applyStopLayers(const LayerHierarchy& hierarchy,
                                           const LayerHierarchy::TraversalPath& traversalPath) {
    ftl::SmallVector<uint32_t, 5> stopLayers;
    ftl::SmallVector<uint32_t, 5> activeStopLayers;
    applyStopLayersInternal(hierarchy, traversalPath, stopLayers, activeStopLayers);
}

void LayerSnapshotBuilder::applyStopLayersInternal(
        const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath& traversalPath,
        ftl::SmallVector<uint32_t, 5>& stopLayers,
        ftl::SmallVector<uint32_t, 5>& activeStopLayers) {
    const RequestedLayerState* layer = hierarchy.getLayer();

    // Push to the stopLayer stack.
    if (layer->stopLayerId != UNASSIGNED_LAYER_ID) {
        stopLayers.push_back(layer->stopLayerId);
    }

    // Hide this layer if the activeStopLayers set is non-empty.
    if (!activeStopLayers.empty()) {
        LayerSnapshot* snapshot = getSnapshot(traversalPath);
        snapshot->isHiddenByPolicyFromParent = true;
    }

    // Traverse z-ordered below children before potentially activating this layer as a stop layer.
    auto childIt = hierarchy.mChildren.begin();
    while (childIt != hierarchy.mChildren.end()) {
        auto& [childHierarchy, childVariant] = *childIt;
        if (childHierarchy->getLayer()->z >= 0) {
            break;
        }
        childIt++;

        LayerHierarchy::TraversalPath childTraversalPath =
                traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant);
        if (childTraversalPath.detached) {
            continue;
        }

        applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers);
    }

    // Activate this layer as a stop layer if it's in the stopLayers stack.
    bool isStopLayer =
            std::find(stopLayers.begin(), stopLayers.end(), layer->id) != stopLayers.end();
    if (isStopLayer) {
        activeStopLayers.push_back(layer->id);
        LayerSnapshot* snapshot = getSnapshot(traversalPath);
        snapshot->isHiddenByPolicyFromParent = true;
    }

    // Traverse z-ordered above children.
    while (childIt != hierarchy.mChildren.end()) {
        auto& [childHierarchy, childVariant] = *childIt++;

        LayerHierarchy::TraversalPath childTraversalPath =
                traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant);
        if (childTraversalPath.detached) {
            continue;
        }

        applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers);
    }

    // Pop from the stopLayer stack and remove active stop layers from the activeStopLayers set
    // if necessary.
    if (layer->stopLayerId != UNASSIGNED_LAYER_ID) {
        stopLayers.pop_back();

        auto it = activeStopLayers.begin();
        while (it != activeStopLayers.end()) {
            bool stopLayerNoLongerActive =
                    std::find(stopLayers.begin(), stopLayers.end(), *it) == stopLayers.end();
            if (stopLayerNoLongerActive) {
                activeStopLayers.unstable_erase(it);
            } else {
                it++;
            }
        }
    }
}

} // namespace android::surfaceflinger::frontend
+5 −0
Original line number Diff line number Diff line
@@ -139,6 +139,11 @@ private:
                                          const Args& args, bool* outChildHasValidFrameRate);
    void updateTouchableRegionCrop(const Args& args);

    void applyStopLayers(const LayerHierarchy&, const LayerHierarchy::TraversalPath&);
    void applyStopLayersInternal(const LayerHierarchy&, const LayerHierarchy::TraversalPath&,
                                 ftl::SmallVector<uint32_t, 5>& stopLayers,
                                 ftl::SmallVector<uint32_t, 5>& activeStopLayers);

    std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*,
                       LayerHierarchy::TraversalPathHash>
            mPathToSnapshot;
Loading