/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "FrontEnd/DisplayInfo.h" #include "FrontEnd/LayerLifecycleManager.h" #include "LayerHierarchy.h" #include "LayerSnapshot.h" #include "RequestedLayerState.h" namespace android::surfaceflinger::frontend { // Walks through the layer hierarchy to build an ordered list // of LayerSnapshots that can be passed on to CompositionEngine. // This builder does a minimum amount of work to update // an existing set of snapshots based on hierarchy changes // and RequestedLayerState changes. // The builder also uses a fast path to update // snapshots when there are only buffer updates. class LayerSnapshotBuilder { public: enum class ForceUpdateFlags { NONE, ALL, HIERARCHY, }; struct Args { LayerHierarchy root; const LayerLifecycleManager& layerLifecycleManager; ForceUpdateFlags forceUpdate = ForceUpdateFlags::NONE; bool includeMetadata = false; const DisplayInfos& displays; // Set to true if there were display changes since last update. bool displayChanges = false; const renderengine::ShadowSettings& globalShadowSettings; bool supportsBlur = true; bool forceFullDamage = false; std::optional parentCrop = std::nullopt; std::unordered_set excludeLayerIds; const std::unordered_map& supportedLayerGenericMetadata; const std::unordered_map& genericLayerMetadataKeyMap; }; LayerSnapshotBuilder(); // Rebuild the snapshots from scratch. LayerSnapshotBuilder(Args); // Update an existing set of snapshot using change flags in RequestedLayerState // and LayerLifecycleManager. This needs to be called before // LayerLifecycleManager.commitChanges is called as that function will clear all // change flags. void update(const Args&); std::vector>& getSnapshots(); LayerSnapshot* getSnapshot(uint32_t layerId) const; LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const; typedef std::function ConstVisitor; // Visit each visible snapshot in z-order void forEachVisibleSnapshot(const ConstVisitor& visitor) const; // Visit each visible snapshot in z-order void forEachVisibleSnapshot(const ConstVisitor& visitor, const LayerHierarchy& root) const; typedef std::function& snapshot)> Visitor; // Visit each visible snapshot in z-order and move the snapshot if needed void forEachVisibleSnapshot(const Visitor& visitor); // Visit each snapshot interesting to input reverse z-order void forEachInputSnapshot(const ConstVisitor& visitor) const; private: friend class LayerSnapshotTest; static LayerSnapshot getRootSnapshot(); // return true if we were able to successfully update the snapshots via // the fast path. bool tryFastUpdate(const Args& args); void updateSnapshots(const Args& args); const LayerSnapshot& updateSnapshotsInHierarchy(const Args&, const LayerHierarchy& hierarchy, LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot, int depth); void updateSnapshot(LayerSnapshot&, const Args&, const RequestedLayerState&, const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath&); static void updateRelativeState(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot, bool parentIsRelative, const Args& args); static void resetRelativeState(LayerSnapshot& snapshot); static void updateRoundedCorner(LayerSnapshot& snapshot, const RequestedLayerState& layerState, const LayerSnapshot& parentSnapshot); void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState, const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags); static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested, const renderengine::ShadowSettings& globalShadowSettings); void updateInput(LayerSnapshot& snapshot, const RequestedLayerState& requested, const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath& path, const Args& args); // Return true if there are unreachable snapshots bool sortSnapshotsByZ(const Args& args); LayerSnapshot* createSnapshot(const LayerHierarchy::TraversalPath& id, const RequestedLayerState& layer, const LayerSnapshot& parentSnapshot); void updateChildState(LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot, const Args& args); void updateTouchableRegionCrop(const Args& args); std::unordered_map mPathToSnapshot; std::multimap mIdToSnapshots; // Track snapshots that needs touchable region crop from other snapshots std::unordered_set mNeedsTouchableRegionCrop; std::vector> mSnapshots; LayerSnapshot mRootSnapshot; bool mResortSnapshots = false; int mNumInterestingSnapshots = 0; }; } // namespace android::surfaceflinger::frontend