blob: 6586901e7027fe30e7ddfbeece34acbaaf0acdc3 [file]
/*
* Copyright 2025 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.
*/
#include <FrontEnd/LayerHierarchy.h>
#include "FrontEnd/Caching/MergeableHierarchy.h"
#include "MergeableHierarchyManager.h"
namespace android::surfaceflinger::frontend::caching {
void MergeableHierarchyManager::update(const LayerHierarchy& hierarchy) {
std::vector<HierarchyEntry> topHierarchies;
std::vector<HierarchyEntry> dependentHierarchies;
update(&hierarchy, topHierarchies, dependentHierarchies);
mMergeableHierarchies.clear();
mMergeableHierarchies.insert(mMergeableHierarchies.end(),
std::make_move_iterator(topHierarchies.begin()),
std::make_move_iterator(topHierarchies.end()));
mMergeableHierarchies.insert(mMergeableHierarchies.end(),
std::make_move_iterator(dependentHierarchies.begin()),
std::make_move_iterator(dependentHierarchies.end()));
}
MergeableHierarchyManager::UpdatePayload MergeableHierarchyManager::update(
const LayerHierarchy* hierarchy, std::vector<HierarchyEntry>& topHierarchies,
std::vector<HierarchyEntry>& dependentHierarchies) {
nsecs_t lastUpdateTime = 0;
int32_t numInterestingChildren = 0;
std::vector<HierarchyEntry> descendentHierarchies;
for (auto& [childHierarchy, _] : hierarchy->mChildren) {
auto updatePayload = update(childHierarchy, descendentHierarchies, dependentHierarchies);
if (updatePayload.containsMergedHierarchy) {
numInterestingChildren++;
}
lastUpdateTime = std::max(lastUpdateTime, updatePayload.lastUpdateTimeIncludingChilderen);
}
if (hierarchy->getLayer() != nullptr) {
lastUpdateTime = std::max(lastUpdateTime, hierarchy->getLayer()->lastUpdateTime);
}
if (lastUpdateTime > 0 && canAddNode(hierarchy, lastUpdateTime)) {
// Don't generate equivalent hierarchies that aren't interesting.
// So check that the root node actually has stuff to draw, or that there's multiple children
// that also can be updated.
if (hierarchy->getLayer()->hasSomethingToDraw() || numInterestingChildren > 1) {
auto newHierarchy =
createOrReuseHierarchy({hierarchy->getLayer()->id, hierarchy, lastUpdateTime});
for (auto& descendentHierarchy : descendentHierarchies) {
descendentHierarchy.isTop = false;
}
dependentHierarchies.insert(dependentHierarchies.end(),
std::make_move_iterator(descendentHierarchies.begin()),
std::make_move_iterator(descendentHierarchies.end()));
topHierarchies.emplace_back(HierarchyEntry{std::move(newHierarchy), true});
return {lastUpdateTime, true};
}
}
topHierarchies.insert(topHierarchies.end(),
std::make_move_iterator(descendentHierarchies.begin()),
std::make_move_iterator(descendentHierarchies.end()));
return {lastUpdateTime, false};
}
void MergeableHierarchyManager::constructSnapshots(
LayerSnapshotBuilder& builder, const LayerSnapshotBuilder::Args& args,
compositionengine::CompositionEngine& compositionEngine,
std::unordered_map<uint32_t, sp<Layer>>& legacyLayers) {
for (auto& hierarchy : mMergeableHierarchies) {
hierarchy.hierarchy.constructSnapshot(builder, args, compositionEngine, legacyLayers);
}
}
} // namespace android::surfaceflinger::frontend::caching