blob: 1cec0183b95bf26113141f3728500b96b0713b21 [file] [log] [blame]
/*
* 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 {
private:
static LayerSnapshot getRootSnapshot();
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 ShadowSettings& globalShadowSettings;
bool supportsBlur = true;
bool forceFullDamage = false;
std::optional<FloatRect> parentCrop = std::nullopt;
std::unordered_set<uint32_t> excludeLayerIds;
const std::unordered_map<std::string, bool>& supportedLayerGenericMetadata;
const std::unordered_map<std::string, uint32_t>& genericLayerMetadataKeyMap;
bool skipRoundCornersWhenProtected = false;
LayerSnapshot rootSnapshot = getRootSnapshot();
};
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<std::unique_ptr<LayerSnapshot>>& getSnapshots();
LayerSnapshot* getSnapshot(uint32_t layerId) const;
LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const;
typedef std::function<void(const LayerSnapshot& snapshot)> 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<void(std::unique_ptr<LayerSnapshot>& 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;
// 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, const Args& args);
void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState,
const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags);
static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested,
const 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 updateFrameRateFromChildSnapshot(LayerSnapshot& snapshot,
const LayerSnapshot& childSnapshot, const Args& args);
void updateTouchableRegionCrop(const Args& args);
std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*,
LayerHierarchy::TraversalPathHash>
mPathToSnapshot;
std::multimap<uint32_t, LayerSnapshot*> mIdToSnapshots;
// Track snapshots that needs touchable region crop from other snapshots
std::unordered_set<LayerHierarchy::TraversalPath, LayerHierarchy::TraversalPathHash>
mNeedsTouchableRegionCrop;
std::vector<std::unique_ptr<LayerSnapshot>> mSnapshots;
bool mResortSnapshots = false;
int mNumInterestingSnapshots = 0;
};
} // namespace android::surfaceflinger::frontend