407 lines
17 KiB
C++
407 lines
17 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
|
|
|
#undef LOG_TAG
|
|
#define LOG_TAG "LayerLifecycleManager"
|
|
|
|
#include "LayerLifecycleManager.h"
|
|
#include "Client.h" // temporarily needed for LayerCreationArgs
|
|
#include "LayerLog.h"
|
|
#include "SwapErase.h"
|
|
|
|
namespace android::surfaceflinger::frontend {
|
|
|
|
using namespace ftl::flag_operators;
|
|
|
|
void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayerState>> newLayers) {
|
|
if (newLayers.empty()) {
|
|
return;
|
|
}
|
|
|
|
mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
|
|
for (auto& newLayer : newLayers) {
|
|
RequestedLayerState& layer = *newLayer.get();
|
|
auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
|
|
if (!inserted) {
|
|
LOG_ALWAYS_FATAL("Duplicate layer id found. New layer: %s Existing layer: %s",
|
|
layer.getDebugString().c_str(),
|
|
it->second.owner.getDebugString().c_str());
|
|
}
|
|
mAddedLayers.push_back(newLayer.get());
|
|
layer.parentId = linkLayer(layer.parentId, layer.id);
|
|
layer.relativeParentId = linkLayer(layer.relativeParentId, layer.id);
|
|
if (layer.layerStackToMirror != ui::INVALID_LAYER_STACK) {
|
|
// if this layer is mirroring a display, then walk though all the existing root layers
|
|
// for the layer stack and add them as children to be mirrored.
|
|
mDisplayMirroringLayers.emplace_back(layer.id);
|
|
for (auto& rootLayer : mLayers) {
|
|
if (rootLayer->isRoot() && rootLayer->layerStack == layer.layerStackToMirror) {
|
|
layer.mirrorIds.emplace_back(rootLayer->id);
|
|
linkLayer(rootLayer->id, layer.id);
|
|
}
|
|
}
|
|
} else {
|
|
// Check if we are mirroring a single layer, and if so add it to the list of children
|
|
// to be mirrored.
|
|
layer.layerIdToMirror = linkLayer(layer.layerIdToMirror, layer.id);
|
|
if (layer.layerIdToMirror != UNASSIGNED_LAYER_ID) {
|
|
layer.mirrorIds.emplace_back(layer.layerIdToMirror);
|
|
}
|
|
}
|
|
layer.touchCropId = linkLayer(layer.touchCropId, layer.id);
|
|
if (layer.isRoot()) {
|
|
updateDisplayMirrorLayers(layer);
|
|
}
|
|
LLOGV(layer.id, "%s", layer.getDebugString().c_str());
|
|
mLayers.emplace_back(std::move(newLayer));
|
|
}
|
|
}
|
|
|
|
void LayerLifecycleManager::onHandlesDestroyed(const std::vector<uint32_t>& destroyedHandles,
|
|
bool ignoreUnknownHandles) {
|
|
std::vector<uint32_t> layersToBeDestroyed;
|
|
for (const auto& layerId : destroyedHandles) {
|
|
auto it = mIdToLayer.find(layerId);
|
|
if (it == mIdToLayer.end()) {
|
|
LOG_ALWAYS_FATAL_IF(!ignoreUnknownHandles, "%s Layerid not found %d", __func__,
|
|
layerId);
|
|
continue;
|
|
}
|
|
RequestedLayerState& layer = it->second.owner;
|
|
LLOGV(layer.id, "%s", layer.getDebugString().c_str());
|
|
layer.handleAlive = false;
|
|
if (!layer.canBeDestroyed()) {
|
|
continue;
|
|
}
|
|
layer.changes |= RequestedLayerState::Changes::Destroyed;
|
|
layersToBeDestroyed.emplace_back(layerId);
|
|
}
|
|
|
|
if (layersToBeDestroyed.empty()) {
|
|
return;
|
|
}
|
|
|
|
mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
|
|
for (size_t i = 0; i < layersToBeDestroyed.size(); i++) {
|
|
uint32_t layerId = layersToBeDestroyed[i];
|
|
auto it = mIdToLayer.find(layerId);
|
|
if (it == mIdToLayer.end()) {
|
|
LOG_ALWAYS_FATAL("%s Layer with id %d not found", __func__, layerId);
|
|
continue;
|
|
}
|
|
|
|
RequestedLayerState& layer = it->second.owner;
|
|
|
|
layer.parentId = unlinkLayer(layer.parentId, layer.id);
|
|
layer.relativeParentId = unlinkLayer(layer.relativeParentId, layer.id);
|
|
if (layer.layerStackToMirror != ui::INVALID_LAYER_STACK) {
|
|
layer.mirrorIds = unlinkLayers(layer.mirrorIds, layer.id);
|
|
swapErase(mDisplayMirroringLayers, layer.id);
|
|
} else {
|
|
layer.layerIdToMirror = unlinkLayer(layer.layerIdToMirror, layer.id);
|
|
layer.mirrorIds.clear();
|
|
}
|
|
|
|
layer.touchCropId = unlinkLayer(layer.touchCropId, layer.id);
|
|
|
|
auto& references = it->second.references;
|
|
for (uint32_t linkedLayerId : references) {
|
|
RequestedLayerState* linkedLayer = getLayerFromId(linkedLayerId);
|
|
if (!linkedLayer) {
|
|
LOG_ALWAYS_FATAL("%s Layerid reference %d not found for %d", __func__,
|
|
linkedLayerId, layer.id);
|
|
continue;
|
|
};
|
|
if (linkedLayer->parentId == layer.id) {
|
|
linkedLayer->parentId = UNASSIGNED_LAYER_ID;
|
|
if (linkedLayer->canBeDestroyed()) {
|
|
linkedLayer->changes |= RequestedLayerState::Changes::Destroyed;
|
|
layersToBeDestroyed.emplace_back(linkedLayer->id);
|
|
}
|
|
}
|
|
if (linkedLayer->relativeParentId == layer.id) {
|
|
linkedLayer->relativeParentId = UNASSIGNED_LAYER_ID;
|
|
}
|
|
if (swapErase(linkedLayer->mirrorIds, layer.id)) {
|
|
linkedLayer->changes |= RequestedLayerState::Changes::Mirror;
|
|
}
|
|
if (linkedLayer->touchCropId == layer.id) {
|
|
linkedLayer->touchCropId = UNASSIGNED_LAYER_ID;
|
|
}
|
|
}
|
|
mIdToLayer.erase(it);
|
|
}
|
|
|
|
auto it = mLayers.begin();
|
|
while (it != mLayers.end()) {
|
|
RequestedLayerState* layer = it->get();
|
|
if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
|
|
LLOGV(layer->id, "destroyed %s", layer->getDebugStringShort().c_str());
|
|
std::iter_swap(it, mLayers.end() - 1);
|
|
mDestroyedLayers.emplace_back(std::move(mLayers.back()));
|
|
if (it == mLayers.end() - 1) {
|
|
it = mLayers.erase(mLayers.end() - 1);
|
|
} else {
|
|
mLayers.erase(mLayers.end() - 1);
|
|
}
|
|
} else {
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState>& transactions,
|
|
bool ignoreUnknownLayers) {
|
|
for (const auto& transaction : transactions) {
|
|
for (const auto& resolvedComposerState : transaction.states) {
|
|
const auto& clientState = resolvedComposerState.state;
|
|
uint32_t layerId = resolvedComposerState.layerId;
|
|
if (layerId == UNASSIGNED_LAYER_ID) {
|
|
ALOGW("%s Handle %p is not valid", __func__, clientState.surface.get());
|
|
continue;
|
|
}
|
|
|
|
RequestedLayerState* layer = getLayerFromId(layerId);
|
|
if (layer == nullptr) {
|
|
LOG_ALWAYS_FATAL_IF(!ignoreUnknownLayers, "%s Layer with layerid=%d not found",
|
|
__func__, layerId);
|
|
continue;
|
|
}
|
|
|
|
if (!layer->handleAlive) {
|
|
LOG_ALWAYS_FATAL("%s Layer's with layerid=%d) is not alive. Possible out of "
|
|
"order LayerLifecycleManager updates",
|
|
__func__, layerId);
|
|
continue;
|
|
}
|
|
|
|
if (transaction.flags & ISurfaceComposer::eAnimation) {
|
|
layer->changes |= RequestedLayerState::Changes::Animation;
|
|
}
|
|
|
|
uint32_t oldParentId = layer->parentId;
|
|
uint32_t oldRelativeParentId = layer->relativeParentId;
|
|
uint32_t oldTouchCropId = layer->touchCropId;
|
|
layer->merge(resolvedComposerState);
|
|
|
|
if (layer->what & layer_state_t::eBackgroundColorChanged) {
|
|
if (layer->bgColorLayerId == UNASSIGNED_LAYER_ID && layer->bgColor.a != 0) {
|
|
LayerCreationArgs
|
|
backgroundLayerArgs(LayerCreationArgs::getInternalLayerId(
|
|
LayerCreationArgs::sInternalSequence++),
|
|
/*internalLayer=*/true);
|
|
backgroundLayerArgs.parentId = layer->id;
|
|
backgroundLayerArgs.name = layer->name + "BackgroundColorLayer";
|
|
backgroundLayerArgs.flags = ISurfaceComposerClient::eFXSurfaceEffect;
|
|
std::vector<std::unique_ptr<RequestedLayerState>> newLayers;
|
|
newLayers.emplace_back(
|
|
std::make_unique<RequestedLayerState>(backgroundLayerArgs));
|
|
RequestedLayerState* backgroundLayer = newLayers.back().get();
|
|
backgroundLayer->bgColorLayer = true;
|
|
backgroundLayer->handleAlive = false;
|
|
backgroundLayer->parentId = layer->id;
|
|
backgroundLayer->z = std::numeric_limits<int32_t>::min();
|
|
backgroundLayer->color = layer->bgColor;
|
|
backgroundLayer->dataspace = layer->bgColorDataspace;
|
|
layer->bgColorLayerId = backgroundLayer->id;
|
|
addLayers({std::move(newLayers)});
|
|
} else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID && layer->bgColor.a == 0) {
|
|
RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
|
|
layer->bgColorLayerId = UNASSIGNED_LAYER_ID;
|
|
bgColorLayer->parentId = unlinkLayer(bgColorLayer->parentId, bgColorLayer->id);
|
|
onHandlesDestroyed({bgColorLayer->id});
|
|
} else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID) {
|
|
RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
|
|
bgColorLayer->color = layer->bgColor;
|
|
bgColorLayer->dataspace = layer->bgColorDataspace;
|
|
bgColorLayer->what |= layer_state_t::eColorChanged |
|
|
layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged;
|
|
bgColorLayer->changes |= RequestedLayerState::Changes::Content;
|
|
mGlobalChanges |= RequestedLayerState::Changes::Content;
|
|
}
|
|
}
|
|
|
|
if (oldParentId != layer->parentId) {
|
|
unlinkLayer(oldParentId, layer->id);
|
|
layer->parentId = linkLayer(layer->parentId, layer->id);
|
|
if (oldParentId == UNASSIGNED_LAYER_ID) {
|
|
updateDisplayMirrorLayers(*layer);
|
|
}
|
|
}
|
|
if (layer->what & layer_state_t::eLayerStackChanged && layer->isRoot()) {
|
|
updateDisplayMirrorLayers(*layer);
|
|
}
|
|
if (oldRelativeParentId != layer->relativeParentId) {
|
|
unlinkLayer(oldRelativeParentId, layer->id);
|
|
layer->relativeParentId = linkLayer(layer->relativeParentId, layer->id);
|
|
}
|
|
if (oldTouchCropId != layer->touchCropId) {
|
|
unlinkLayer(oldTouchCropId, layer->id);
|
|
layer->touchCropId = linkLayer(layer->touchCropId, layer->id);
|
|
}
|
|
|
|
mGlobalChanges |= layer->changes;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LayerLifecycleManager::commitChanges() {
|
|
for (auto layer : mAddedLayers) {
|
|
for (auto& listener : mListeners) {
|
|
listener->onLayerAdded(*layer);
|
|
}
|
|
}
|
|
mAddedLayers.clear();
|
|
|
|
for (auto& layer : mLayers) {
|
|
layer->clearChanges();
|
|
}
|
|
|
|
for (auto& destroyedLayer : mDestroyedLayers) {
|
|
for (auto& listener : mListeners) {
|
|
listener->onLayerDestroyed(*destroyedLayer);
|
|
}
|
|
}
|
|
mDestroyedLayers.clear();
|
|
mGlobalChanges.clear();
|
|
}
|
|
|
|
void LayerLifecycleManager::addLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
|
|
mListeners.emplace_back(std::move(listener));
|
|
}
|
|
|
|
void LayerLifecycleManager::removeLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
|
|
swapErase(mListeners, listener);
|
|
}
|
|
|
|
const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getLayers() const {
|
|
return mLayers;
|
|
}
|
|
|
|
const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getDestroyedLayers()
|
|
const {
|
|
return mDestroyedLayers;
|
|
}
|
|
|
|
const ftl::Flags<RequestedLayerState::Changes> LayerLifecycleManager::getGlobalChanges() const {
|
|
return mGlobalChanges;
|
|
}
|
|
|
|
RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) {
|
|
if (id == UNASSIGNED_LAYER_ID) {
|
|
return nullptr;
|
|
}
|
|
auto it = mIdToLayer.find(id);
|
|
if (it == mIdToLayer.end()) {
|
|
return nullptr;
|
|
}
|
|
return &it->second.owner;
|
|
}
|
|
|
|
std::vector<uint32_t>* LayerLifecycleManager::getLinkedLayersFromId(uint32_t id) {
|
|
if (id == UNASSIGNED_LAYER_ID) {
|
|
return nullptr;
|
|
}
|
|
auto it = mIdToLayer.find(id);
|
|
if (it == mIdToLayer.end()) {
|
|
return nullptr;
|
|
}
|
|
return &it->second.references;
|
|
}
|
|
|
|
uint32_t LayerLifecycleManager::linkLayer(uint32_t layerId, uint32_t layerToLink) {
|
|
if (layerId == UNASSIGNED_LAYER_ID) {
|
|
return UNASSIGNED_LAYER_ID;
|
|
}
|
|
|
|
std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
|
|
if (!linkedLayers) {
|
|
ALOGV("Could not find layer id %d to link %d. Parent is probably destroyed", layerId,
|
|
layerToLink);
|
|
return UNASSIGNED_LAYER_ID;
|
|
}
|
|
linkedLayers->emplace_back(layerToLink);
|
|
return layerId;
|
|
}
|
|
|
|
uint32_t LayerLifecycleManager::unlinkLayer(uint32_t layerId, uint32_t linkedLayer) {
|
|
std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
|
|
if (!linkedLayers) {
|
|
return UNASSIGNED_LAYER_ID;
|
|
}
|
|
swapErase(*linkedLayers, linkedLayer);
|
|
return UNASSIGNED_LAYER_ID;
|
|
}
|
|
|
|
std::vector<uint32_t> LayerLifecycleManager::unlinkLayers(const std::vector<uint32_t>& layerIds,
|
|
uint32_t linkedLayer) {
|
|
for (uint32_t layerId : layerIds) {
|
|
unlinkLayer(layerId, linkedLayer);
|
|
}
|
|
return {};
|
|
}
|
|
|
|
std::string LayerLifecycleManager::References::getDebugString() const {
|
|
std::string debugInfo = owner.name + "[" + std::to_string(owner.id) + "] refs:";
|
|
std::for_each(references.begin(), references.end(),
|
|
[&debugInfo = debugInfo](const uint32_t& reference) mutable {
|
|
debugInfo += std::to_string(reference) + ",";
|
|
});
|
|
return debugInfo;
|
|
}
|
|
|
|
void LayerLifecycleManager::fixRelativeZLoop(uint32_t relativeRootId) {
|
|
auto it = mIdToLayer.find(relativeRootId);
|
|
if (it == mIdToLayer.end()) {
|
|
return;
|
|
}
|
|
RequestedLayerState& layer = it->second.owner;
|
|
layer.relativeParentId = unlinkLayer(layer.relativeParentId, layer.id);
|
|
layer.changes |=
|
|
RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::RelativeParent;
|
|
mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
|
|
}
|
|
|
|
// Some layers mirror the entire display stack. Since we don't have a single root layer per display
|
|
// we have to track all these layers and update what they mirror when the list of root layers
|
|
// on a display changes. This function walks through the list of display mirroring layers
|
|
// and updates its list of layers that its mirroring. This function should be called when a new
|
|
// root layer is added, removed or moved to another display.
|
|
void LayerLifecycleManager::updateDisplayMirrorLayers(RequestedLayerState& rootLayer) {
|
|
for (uint32_t mirrorLayerId : mDisplayMirroringLayers) {
|
|
RequestedLayerState* mirrorLayer = getLayerFromId(mirrorLayerId);
|
|
bool canBeMirrored =
|
|
rootLayer.isRoot() && rootLayer.layerStack == mirrorLayer->layerStackToMirror;
|
|
bool currentlyMirrored =
|
|
std::find(mirrorLayer->mirrorIds.begin(), mirrorLayer->mirrorIds.end(),
|
|
rootLayer.id) != mirrorLayer->mirrorIds.end();
|
|
|
|
if (canBeMirrored && !currentlyMirrored) {
|
|
mirrorLayer->mirrorIds.emplace_back(rootLayer.id);
|
|
linkLayer(rootLayer.id, mirrorLayer->id);
|
|
mirrorLayer->changes |= RequestedLayerState::Changes::Mirror;
|
|
} else if (!canBeMirrored && currentlyMirrored) {
|
|
swapErase(mirrorLayer->mirrorIds, rootLayer.id);
|
|
unlinkLayer(rootLayer.id, mirrorLayer->id);
|
|
mirrorLayer->changes |= RequestedLayerState::Changes::Mirror;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace android::surfaceflinger::frontend
|